diff --git a/README.md b/README.md index 9ab8d36ba..9f3a1f0e9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![ui](/assets/banner.png) -

Let AI build multi-agent workflows for you in minutes

+

Let AI build you coworkers

@@ -35,23 +35,19 @@

+

+⚑ Build AI agents instantly with natural language | πŸ”Œ Connect tools with one-click integrations | πŸ“‚ Power with knowledge by adding documents for RAG | πŸ”„ Automate workflows by setting up triggers and actions | πŸš€ Deploy anywhere via API or SDK

+☁️ Prefer a hosted version? Use our cloud to starting building agents right away! +

-- ✨ **Start from an idea -> copilot builds your multi-agent workflows** - - E.g. "Build me an assistant for a food delivery company to handle delivery status and missing items. Include the necessary tools." -- 🌐 **Connect MCP servers** - - Add the MCP servers in settings -> import the tools into Rowboat. -- πŸ“ž **Integrate into your app using the HTTP API or Python SDK** - - Grab the project ID and generated API key from settings and use the API. - -Powered by OpenAI's Agents SDK, Rowboat is the fastest way to build multi-agents! ## Quick start 1. Set your OpenAI key - ```bash - export OPENAI_API_KEY=your-openai-api-key + ```bash + export OPENAI_API_KEY=your-openai-api-key ``` -2. Clone the repository and start Rowboat +2. Clone the repository and start Rowboat (requires Docker) ```bash git clone git@github.com:rowboatlabs/rowboat.git cd rowboat @@ -60,71 +56,30 @@ Powered by OpenAI's Agents SDK, Rowboat is the fastest way to build multi-agents 3. Access the app at [http://localhost:3000](http://localhost:3000). -Note: We have added native RAG support including file-uploads and URL scraping. See the [RAG](https://docs.rowboatlabs.com/using_rag) section of our docs for this. - -Note: See the [Using custom LLM providers](https://docs.rowboatlabs.com/setup/#using-custom-llm-providers) section of our docs for using custom providers like OpenRouter and LiteLLM. +To add tools, RAG, more LLMs, and triggers checkout the [Advanced](#advanced) section below. -## Demo +## Demos +#### Meeting-prep assistant +Chat with the copilot to build a meeting-prep workflow, then add a calendar invite as a trigger. Watch the full demo [here](https://youtu.be/KZTP4xZM2DY). +[![meeting-prep](https://github.com/user-attachments/assets/27755ef5-6549-476f-b9c0-50bef8770384)](https://youtu.be/KZTP4xZM2DY) -#### Create a multi-agent assistant with MCP tools by chatting with Rowboat -[![Screenshot 2025-04-23 at 00 25 31](https://github.com/user-attachments/assets/c8a41622-8e0e-459f-becb-767503489866)](https://youtu.be/YRTCw9UHRbU) +#### Customer support assistant +Chat with the copilot to build a customer support assistant, then connect your MCP server, and data for RAG. Watch the full demo [here](https://youtu.be/Xfo-OfgOl8w). +[![output](https://github.com/user-attachments/assets/97485fd7-64c3-4d60-a627-f756a89dee64)](https://youtu.be/Xfo-OfgOl8w) -## Integrate with Rowboat agents +#### Personal assistant +Chat with the copilot to build a personal assistant. Watch the full demo [here](https://youtu.be/6r7P4Vlcn2g). +[![personal-assistant](https://github.com/user-attachments/assets/0f1c0ffd-23ba-4b49-8bfb-ec7a846f1332)](https://youtu.be/6r7P4Vlcn2g) -There are 2 ways to integrate with the agents you create in Rowboat +## Advanced +1. Native RAG Support: Enable file uploads and URL scraping with Rowboat's built-in RAG capabilities – see [RAG Guide](https://docs.rowboatlabs.com/docs/using-rowboat/rag). -1. HTTP API - - You can use the API directly at [http://localhost:3000/api/v1/](http://localhost:3000/api/v1/) - - See [API Docs](https://docs.rowboatlabs.com/using_the_api/) for details - ```bash - curl --location 'http://localhost:3000/api/v1//chat' \ - --header 'Content-Type: application/json' \ - --header 'Authorization: Bearer ' \ - --data '{ - "messages": [ - { - "role": "user", - "content": "tell me the weather in london in metric units" - } - ], - "state": null - }' - ``` - +2. Custom LLM Providers: Use any LLM provider, including aggregators like OpenRouter and LiteLLM - see [Using more LLM providers](https://docs.rowboatlabs.com/docs/using-rowboat/customise/custom-llms). -2. Python SDK - You can use the included Python SDK to interact with the Agents - ``` - pip install rowboat - ``` +3. Tools & Triggers: Add tools and event triggers (e.g., Gmail, Slack) for automation – see [Tools](https://docs.rowboatlabs.com/docs/using-rowboat/tools) & [Triggers](https://docs.rowboatlabs.com/docs/using-rowboat/triggers). - See [SDK Docs](https://docs.rowboatlabs.com/using_the_sdk/) for details. Here is a quick example: - ```python - from rowboat import Client, StatefulChat - from rowboat.schema import UserMessage, SystemMessage - - # Initialize the client - client = Client( - host="http://localhost:3000", - project_id="", - api_key="" - ) - - # Create a stateful chat session (recommended) - chat = StatefulChat(client) - response = chat.run("What's the weather in London?") - print(response) - - # Or use the low-level client API - messages = [ - SystemMessage(role='system', content="You are a helpful assistant"), - UserMessage(role='user', content="Hello, how are you?") - ] - - # Get response - response = client.chat(messages=messages) - print(response.messages[-1].content) - ``` +4. API & SDK: Integrate Rowboat agents directly into your app – see [API](https://docs.rowboatlabs.com/docs/api-sdk/using_the_api) & [SDK](https://docs.rowboatlabs.com/docs/api-sdk/using_the_sdk) docs. +## Refer to [Docs](https://docs.rowboatlabs.com/) to learn how to start building agents with Rowboat. diff --git a/apps/docs/Dockerfile b/apps/docs/Dockerfile deleted file mode 100644 index f17732115..000000000 --- a/apps/docs/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM python:3.12 - -WORKDIR /app - -COPY requirements.txt . - -RUN pip install -r requirements.txt - -COPY . . - -CMD ["mkdocs", "serve", "--dev-addr", "0.0.0.0:8000"] \ No newline at end of file diff --git a/apps/docs/docs.json b/apps/docs/docs.json new file mode 100644 index 000000000..3c381b703 --- /dev/null +++ b/apps/docs/docs.json @@ -0,0 +1,84 @@ +{ + "$schema": "https://mintlify.com/docs.json", + "theme": "maple", + "name": "Rowboat", + "description": "Rowboat is an open-source platform for building multi-agent systems. It helps you orchestrate tools, RAG, memory, and deployable agents with ease.", + "favicon": "/favicon.ico", + "colors": { + "primary": "#6366F1", + "light": "#6366F1", + "dark": "#6366F1" + }, + "icons": { + "library": "fontawesome" + }, + "navigation": { + "groups": [ + { + "group": "Getting Started", + "pages": [ + "docs/getting-started/introduction", + "docs/getting-started/quickstart", + "docs/getting-started/license" + ] + }, + { + "group": "Using Rowboat", + "pages": [ + "docs/using-rowboat/rowboat-studio", + "docs/using-rowboat/agents", + "docs/using-rowboat/tools", + "docs/using-rowboat/rag", + "docs/using-rowboat/triggers", + "docs/using-rowboat/jobs", + "docs/using-rowboat/conversations", + { + "group": "Customise", + "icon": "sliders", + "pages": [ + "docs/using-rowboat/customise/custom-llms" + ] + } + ] + }, + { + "group": "API & SDK", + "pages": ["docs/api-sdk/using_the_api", "docs/api-sdk/using_the_sdk"] + }, + { + "group": "Development", + "pages": ["docs/development/contribution-guide", "docs/development/roadmap"] + } + ] + }, + "background": { + "decoration": "gradient", + "color": { + "light": "#FFFFFF", + "dark": "#0D0A09" + } + }, + "navbar": { + "primary": { + "type": "button", + "label": "Try Rowboat", + "href": "https://app.rowboatlabs.com" + } + }, + "footer": { + "socials": { + "github": "https://github.com/rowboatlabs/rowboat", + "linkedin": "https://www.linkedin.com/company/rowboat-labs", + "discord": "https://discord.gg/rxB8pzHxaS" + } + }, + "contextual": { + "options": [ + "copy", + "view", + "chatgpt", + "claude" + ] + } + } + \ No newline at end of file diff --git a/apps/docs/docs/CNAME b/apps/docs/docs/CNAME deleted file mode 100644 index 5ece9e384..000000000 --- a/apps/docs/docs/CNAME +++ /dev/null @@ -1 +0,0 @@ -docs.rowboatlabs.com \ No newline at end of file diff --git a/apps/docs/docs/add_tools.md b/apps/docs/docs/add_tools.md deleted file mode 100644 index f67792959..000000000 --- a/apps/docs/docs/add_tools.md +++ /dev/null @@ -1,56 +0,0 @@ -## Add tools to agents -In Rowboat, you can add tools to your agents by (a) selecting from a in-built library of MCP tools (b) adding your own customer MCP servers (c) integrating your APIs through a webhook (e) mocking tool calls to test the system. - -### Adding MCP tools - -#### Hosted MCP Library - -Rowboat has partnered with ![Kavis AI](https://www.klavis.ai/) to provide a growing library of hosted MCP servers. You can obtain a Klavis API key and set it using: -```bash -export KLAVIS_API_KEY=your-klavis-api-key -``` - -![Library](img/mcp-library.png) - -Enable any of the hosted MCP servers by clicking on the enable button. The server will take approximately 10 seconds to spin up. - -![Library](img/enable-mcp-server.png) - -For most servers, you will need to authorize it by clicking on the 'Auth' button and connecting to your account e.g. connecting to you github or slack account - -The servers you have enabled will show up under tools section in the build view and can be added to any of the agents. - -![Library](img/mcp-tools-build-view.png) - -Note: For GSuite tools, you need to get a Google Client ID and set it using: -```bash -export KLAVIS_GOOGLE_CLIENT_ID=your-google-client-id -``` - -To obtain a Google Client ID: -1. Go to the [Google Cloud Console](https://console.cloud.google.com) -2. Create a new project or select an existing one -3. Go to "APIs & Services" β†’ "OAuth consent screen" and complete the setup -4. Go to "APIs & Services" β†’ "Credentials" β†’ "OAuth client ID" and create credentials for web application. - -#### Custom MCP Server -You can add any running MCP server in Settings -> Tools. - -![Example Tool](img/add-mcp-server.png) - -You can use [supergateway](https://github.com/supercorp-ai/supergateway) to expose any MCP stdio server as an SSE server. - -Now, you can import the tools from the MCP server in the Build view. - -![Example Tool](img/import-mcp-tools.png) - -### Adding mock tools -You can mock any tool you have created by checking the 'Mock tool responses' option. - - -![Example Tool](img/mock-tool.png) - -### Debug tool calls in the playground -When agents call tools during a chat in the playground, the tool call parameters and response are available for debugging real-time. For testing purposes, the platform can produce mock tool responses in the playground, without integrating actual tools. - -![Mock Tool Responses](img/mock-response.png) \ No newline at end of file diff --git a/apps/docs/docs/agents.md b/apps/docs/docs/agents.md deleted file mode 100644 index 6ffb91a39..000000000 --- a/apps/docs/docs/agents.md +++ /dev/null @@ -1,29 +0,0 @@ -# Agents - -## Overview -- Agents carry out a specific part of the conversation and / or perform tasks like orchestrating between other agents, triggering internal processes and fetching information. -- Agents carry out tasks through tools provided to them. -- Agents can be connected to other agents through a mention in the agent's instruction. - -## Agent Configurations - -### Description -The description conveys the agent's role in the multi-agent system. Writing a good description is important for other agents to know when to pass control of the conversation to an agent. - -### Instructions -Agent instructions are the backbone of an agent, defining its behavior. RowBoat Studio's copilot produces a good framework for agent instructions, involving Role, Steps to Follow, Scope and Guidelines. Since agents are powered by LLMs, general best practices while writing prompts apply. - -### Examples -The agent uses examples as a reference for behavior in different scenarios. While there are no prescribed formats to provide examples in, examples should include what the user might say, what the agent should respond with as well as indications of any tool calls to be made. - -### Prompts -Prompts attached to an agent will be used by the agent in addition to instructions. - -### Tools -Tools attached to an agent will be put out as tool calls. The behavior of when to invoke tools can be fine-tuned by specifying corresponding instructions or prompts. Adding examples to agents can also be useful in controlling tool call behavior. - -### Connected Agents -In the agent instructions, the connected agents are shown with an '@mention'. If the agent mentioned in an instruction (connected agent) does not actually exist, the connected agent's name would show up with an '!' to call to attention. - -### Model -RowBoat currently supports OpenAI LLMs. Agents can be configured to use GPT-4o or GPT-4o-mini. \ No newline at end of file diff --git a/apps/docs/docs/using_the_api.md b/apps/docs/docs/api-sdk/using_the_api.mdx similarity index 91% rename from apps/docs/docs/using_the_api.md rename to apps/docs/docs/api-sdk/using_the_api.mdx index 413540ab2..60125b909 100644 --- a/apps/docs/docs/using_the_api.md +++ b/apps/docs/docs/api-sdk/using_the_api.mdx @@ -1,14 +1,21 @@ -# Using the API +--- +title: "Using the API" +description: "This is a guide on using the HTTP API to power conversations with the assistant created in Studio." +icon: "code" +--- -This is a guide on using the HTTP API to power conversations with the assistant created in Studio. ## Deploy your assistant to production on Studio -![Prod Deploy](img/prod-deploy.png) + + Prod Deploy + ## Obtain API key and Project ID Generate API keys via the developer configs in your project. Copy the Project ID from the same page. -![Developer Configs](img/dev-config.png) + + Developer Configs + ## API Endpoint diff --git a/apps/docs/docs/api-sdk/using_the_sdk.mdx b/apps/docs/docs/api-sdk/using_the_sdk.mdx new file mode 100644 index 000000000..0909224ff --- /dev/null +++ b/apps/docs/docs/api-sdk/using_the_sdk.mdx @@ -0,0 +1,91 @@ +--- +title: "Using the SDK" +description: "This is a guide on using the RowBoat Python SDK as an alternative to the [RowBoat HTTP API](/using_the_api) to power conversations with the assistant created in Studio." +icon: "toolbox" +--- + +## Prerequisites +- ``` pip install rowboat ``` +- [Deploy your assistant to production](/using_the_api/#deploy-your-assistant-to-production-on-studio) +- [Obtain your `` and ``](/using_the_api/#obtain-api-key-and-project-id) + +### API Host +- For the open source installation, the `` is [http://localhost:3000](http://localhost:3000) +- When using the hosted app, the `` is [https://app.rowboatlabs.com](https://app.rowboatlabs.com) + +## Usage + +### Basic Usage + +The main way to interact with Rowboat is using the `Client` class, which provides a stateless chat API. You can manage conversation state using the `conversationId` returned in each response. + +```python +from rowboat.client import Client +from rowboat.schema import UserMessage + +# Initialize the client +client = Client( + host="", + projectId="", + apiKey="" +) + +# Start a new conversation +result = client.run_turn( + messages=[ + UserMessage(role='user', content="What is the capital of France?") + ] +) +print(result.turn.output[-1].content) +# The capital of France is Paris. + +print("Conversation ID:", result.conversationId) + +# Continue the conversation by passing the conversationId +result = client.run_turn( + messages=[ + UserMessage(role='user', content="What other major cities are in that country?") + ], + conversationId=result.conversationId +) +print(result.turn.output[-1].content) +# Other major cities in France include Lyon, Marseille, Toulouse, and Nice. + +result = client.run_turn( + messages=[ + UserMessage(role='user', content="What's the population of the first city you mentioned?") + ], + conversationId=result.conversationId +) +print(result.turn.output[-1].content) +# Lyon has a population of approximately 513,000 in the city proper. +``` + +### Using Tool Overrides (Mock Tools) + +You can provide tool override instructions to test a specific configuration using the `mockTools` argument: + +```python +result = client.run_turn( + messages=[ + UserMessage(role='user', content="What's the weather?") + ], + mockTools={ + "weather_lookup": "The weather in any city is sunny and 25Β°C.", + "calculator": "The result of any calculation is 42." + } +) +print(result.turn.output[-1].content) +``` + +### Message Types + +You can use different message types as defined in `rowboat.schema`, such as `UserMessage`, `SystemMessage`, `AssistantMessage`, etc. See `schema.py` for all available message types. + +### Error Handling + +If the API returns a non-200 status code, a `ValueError` will be raised with the error details. + +--- + +For more advanced usage, see the docstrings in `client.py` and the message schemas in `schema.py`. \ No newline at end of file diff --git a/apps/docs/docs/create_agents.md b/apps/docs/docs/create_agents.md deleted file mode 100644 index 72ee7853d..000000000 --- a/apps/docs/docs/create_agents.md +++ /dev/null @@ -1,14 +0,0 @@ -## Create the set of initial agents -Copilot can set up agents for you from scratch. - -### Instruct copilot -First, tell it about the initial set of agents that make up your assistant. - -![Agent Config](img/create-agents-delivery.png) - -Using copilot to create your initial set of agents helps you leverage best practices in formatting agent instructions and connecting agents to each other as a graph, all of which have been baked into copilot. - -### Inspect the agents -Once you apply changes, inspect the agents to see how copilot has built them. Specifically, note the Instructions, and Examples in each agent. - -![Agent Config](img/agent-instruction.png) diff --git a/apps/docs/docs/data_sources.md b/apps/docs/docs/data_sources.md deleted file mode 100644 index fcc39fe6d..000000000 --- a/apps/docs/docs/data_sources.md +++ /dev/null @@ -1 +0,0 @@ -Coming soon. \ No newline at end of file diff --git a/apps/docs/docs/development/contribution-guide.mdx b/apps/docs/docs/development/contribution-guide.mdx new file mode 100644 index 000000000..94d0f46c9 --- /dev/null +++ b/apps/docs/docs/development/contribution-guide.mdx @@ -0,0 +1,59 @@ +--- +title: "Contribution Guide" +description: "Learn how to contribute to the Rowboat project and help improve our platform." +icon: "github" +--- + +# Join the Rowboat Voyage + +We're building Rowboat as an open-source, community-powered platform β€” and we'd love for you to hop aboard! Whether you're fixing typos, suggesting a new tool integration, or designing your dream multi-agent workflow, your contributions are valuable and welcome. + + + Contribution guide hero image showing community collaboration + + +--- + +## How You Can Contribute + + +- **Tackle Open Issues** + Browse our [GitHub Issues](https://github.com/rowboatlabs/rowboat/issues) for tags like `good first issue`, `help wanted`, or `bug` to find a spot that fits your skillset. + +- **Join the Community** + Our [Discord](https://discord.gg/rxB8pzHxaS) is the go-to hub for brainstorming, feedback, and finding contributors for bigger efforts. + +- **Propose Something New** + Have a new tool integration idea or found a bug? Open an issue and let’s discuss it! + + +--- + +## Contribution Workflow & Best Practices + +Whether it's your first contribution or your fiftieth, here's what a great contribution looks like: + +| Step / Tip | Description | +|-------------------------------|-----------------------------------------------------------------------------------------------| +| **1. Fork the Repository** | Create a personal copy of [rowboatlabs/rowboat](https://github.com/rowboatlabs/rowboat) to start contributing. | +| **2. Create a New Branch** | Use a descriptive name like `fix-tool-crash` or `feature-new-mcp`. Avoid committing to `main`. | +| **3. Make Your Changes** | Focus your PR on a single issue or feature to keep things clean and reviewable. | +| **4. Write Tests if Needed** | If you change logic, add relevant tests so your contribution is future-proof. | +| **5. Run Tests & Lint Locally**| Make sure your branch passes all tests and code quality checks before pushing. | +| **6. Document or Demo It** | Add helpful context: screenshots, example scripts, or a short video/gif to demonstrate your changes. | +| **7. Submit a Pull Request** | Open a PR with a clear description of your changes and any context reviewers should know. | +| **8. Collaborate on Feedback** | Our maintainers may leave comments β€” it’s all part of the process. Let’s improve it together. | +| **9. Don’t Be Shy to Follow Up** | Feel free to ping the PR/issue if you're waiting on feedback. We appreciate polite nudges. | +| **10. Celebrate the Merge!** | You just made Rowboat better. Thanks for contributing πŸš€ | + +If you're fixing typos, spacing, or small tweaks β€” try bundling those into a related PR instead of sending them standalone. It helps keep reviews focused. + + + +--- + +## Come Build With Us + +We believe great ideas come from the community β€” and that means **you**. Whether you're an engineer, designer, AI tinkerer, or curious beginner, there’s room on this boat for everyone. + +Let’s build the future of AI workflows β€” together. 🫢 diff --git a/apps/docs/docs/development/roadmap.mdx b/apps/docs/docs/development/roadmap.mdx new file mode 100644 index 000000000..6248e5673 --- /dev/null +++ b/apps/docs/docs/development/roadmap.mdx @@ -0,0 +1,7 @@ +--- +icon: "road" +--- + +# Roadmap + +Explore the future development plans and upcoming features for Rowboat. \ No newline at end of file diff --git a/apps/docs/docs/getting-started/introduction.mdx b/apps/docs/docs/getting-started/introduction.mdx new file mode 100644 index 000000000..8fde54db3 --- /dev/null +++ b/apps/docs/docs/getting-started/introduction.mdx @@ -0,0 +1,78 @@ +--- +title: "Introduction" +description: "Welcome to the official Rowboat documentation! Rowboat is a low-code AI IDE to build tool connected multi-agent assistants. Rowboat copilot builds the agents for you based on your requirements with the option do everything manually as well." +icon: "book-open" +--- + + + Intro Video + + +## What is RowBoat? +**RowBoat is a state-of-art platform to build multi-agent AI systems in a visual interface, with the help of a copilot.** + +RowBoat enables you to build, manage and deploy user-facing assistants. An assistant is made up of multiple agents, each having access to a set of tools and working together to interact with the user as a single assistant. You can connect any tool to the agents. + +For example, you can build a *meeting prep assistant* that helps you prepare for upcoming meetings. One agent can access your Google Calendar to see your scheduled meetings, another agent can research the meeting attendees (such as finding their LinkedIn profiles or recent news), and a third agent can compile this research and send it to your email before the meeting. This way, you get automated, personalized meeting prep without manual effort. + +--- + +## How RowBoat works + +### RowBoat Studio +RowBoat Studio lets you create AI agents in minutes, using a visual interface and plain language. +There are key components that you will work with: +- Agents +- Playground +- Copilot + + + + Learn about Rowboat Studio and key concepts used in building assistants + + + +### RowBoat Chat API & SDK +- [RowBoat Chat API](/docs/api-sdk/using_the_api) is a stateless HTTP API to interface with the assistant created on RowBoat Studio. You can use the API to drive end-user facing conversations in your app or website. +- [RowBoat Chat SDK](/docs/api-sdk/using_the_sdk) is a simple Python SDK which wraps the HTTP API under the hood. It provides a clean interface for managing conversations using conversation IDs for state management. + +--- + +## Why RowBoat? +Rowboat is the fastest way to build and deploy multi-agent assistants. + + + + Use plain language and a powerful visual interface to design and orchestrate multi-agent assistants with ease. + + + + Add tools and connect to MCP servers in just minutes β€” no complex setup required. + + + + Accelerate development with battle-tested tooling tailored for building production-ready, multi-agent AI systems. + + + +--- + +## Contributing +Want to contribute to Rowboat? Please consider checking out our [Contribution Guide](/docs/development/contribution-guide) + +Star us on github! + + +## Community +Need help using Rowboat? Join our community! + +Join our growing discord community and interact with hundreds of developer using Rowboat! + diff --git a/apps/docs/docs/license.md b/apps/docs/docs/getting-started/license.mdx similarity index 98% rename from apps/docs/docs/license.md rename to apps/docs/docs/getting-started/license.mdx index a38ae9b91..3e21a84e2 100644 --- a/apps/docs/docs/license.md +++ b/apps/docs/docs/getting-started/license.mdx @@ -1,3 +1,10 @@ +--- +title: "License" +icon: "file" +mode: "center" +# url: "https://github.com/rowboatlabs/rowboat/blob/main/LICENSE" ## An alternate display we could use +--- + RowBoat is available under the [Apache 2.0 License](https://github.com/rowboatlabs/rowboat/blob/main/LICENSE): ---- diff --git a/apps/docs/docs/getting-started/quickstart.mdx b/apps/docs/docs/getting-started/quickstart.mdx new file mode 100644 index 000000000..04fc761b7 --- /dev/null +++ b/apps/docs/docs/getting-started/quickstart.mdx @@ -0,0 +1,94 @@ +--- +title: "Quickstart" +description: "guide to getting started with rowboat" +icon: "rocket" +--- +--- +# Cloud Setup + +Using the open-source version of Rowboat requires more technical skill to set up and navigate. For the smoothest experience, we recommend using our [hosted version](https://dev.rowboatlabs.com/) + +--- + +# Local Setup + +Pre-requisite: Ensure Docker is installed on your machine. You'll also need an OpenAI account and API key to use the Copilot and agents. + + + + + Export your OpenAI API key in your terminal: + + ```bash + export OPENAI_API_KEY=your-openai-api-key + ``` + + + + To use external tools and triggers, export your Composio API key: + + ```bash + export COMPOSIO_API_KEY=your-composio-api-key + export COMPOSIO_TRIGGERS_WEBHOOK_SECRET=your-webhook-secret + ``` + + For more detailed setup instructions, see the [Triggers](/docs/using-rowboat/triggers#local-setup) page. + + + + Clone the Rowboat repository and start the app using Docker: + + ```bash + git clone git@github.com:rowboatlabs/rowboat.git + cd rowboat + ./start.sh + ``` + + + + Once Docker is running, open your browser and go to: + + [http://localhost:3000](http://localhost:3000) + + + + +See the [Using custom LLM providers](#using-custom-llm-providers) section below for using custom providers like OpenRouter and LiteLLM. + +--- + +## Demo +{/* (would be better to change this to a Getiing Started Tutorial) */} + +#### Create a multi-agent assistant with MCP tools by chatting with Rowboat +[![Screenshot 2025-04-23 at 00 25 31](https://github.com/user-attachments/assets/c8a41622-8e0e-459f-becb-767503489866)](https://youtu.be/YRTCw9UHRbU) + +--- + +## Integrate with Rowboat agents + +There are 2 ways to integrate with the agents you create in Rowboat + + + + + Guide on using the HTTP API + + + + Guide on using the Python SDK + + + + +--- + +## Using custom LLM providers +By default, Rowboat uses OpenAI LLMs (gpt-4o, gpt-4.1, etc.) for both agents and copilot, when you export your OPENAI_API_KEY. + +However, you can also configure custom LLM providers (e.g. LiteLLM, OpenRouter) to use any of the hundreds of available LLMs beyond OpenAI, such as Claude, DeepSeek, Ollama LLMs and so on. + +Check out our page on customising + + Learn more about customising your Rowboat experience here + diff --git a/apps/docs/docs/graph.md b/apps/docs/docs/graph.md deleted file mode 100644 index c5d47e951..000000000 --- a/apps/docs/docs/graph.md +++ /dev/null @@ -1,23 +0,0 @@ -# Graph-based Framework - -## Overview - -- Multi-agent systems are popularly represented as graphs, where each agent is a node in the graph. -- In RowBoat, agents are connected to each other as Directed Acyclic Graphs (DAG). -- The graph is also called a workflow, which defines agents, tools, and their connections. -- Since the graph is directed, the control of conversation flows from "parent" agents to their "children" agents -- Every agent is responsible for carrying out a specific part of the workflow, which can involve conversing with the user and / or carrying out tasks such as directing the conversation to other agents. -- [Langgraph](https://www.langchain.com/langgraph) and [Swarm](https://github.com/openai/swarm) are examples of open-source frameworks used to define multi-agent graphs. RowBoat currently supports a Swarm implementation and will extend to Langgraph too in the future. - -## Control Passing - -- While defining the workflow, an agent is designated as the Start agent, to which the first turn of chat will be directed. Typically the Start agent is responsible for triaging the user's query at a high-level and passing control to relevant specific agents which can address the user's needs. -- In any turn of chat, the agent currently in control of the chat has one of 3 options: a) respond to the user (or put out tool calls), b) transfer the chat to any of its children agents or c) transfer the chat back to its parent agent. -- Agents use internal tool calls to transfer the chat to other agents. -- Thus, control passing is achieved by allowing agents to decide flow of control autonomously. -- To the user, the assistant will appear as a unified system, while agents work under the hood. - -## Pipelines - -- RowBoat also has the concept of pipelines - specialized agents invoked sequentially after an agent in the graph has produced a user-facing response. -- E.g. a pipeline with a post processing agent and a guardrail agent will ensure that every response is post processed and guardrailed for appropriateness before presenting it to the user. diff --git a/apps/docs/docs/hosted_setup.md b/apps/docs/docs/hosted_setup.md deleted file mode 100644 index 27f9eabe3..000000000 --- a/apps/docs/docs/hosted_setup.md +++ /dev/null @@ -1,156 +0,0 @@ -# Using the Hosted App - -- This is the developers guide to self-hosting the open-source version of RowBoat. -- Please see our [Introduction](/) page before referring to this guide. -- For direct installation steps, please head to the README of RowBoat's Github repo: [@rowboatlabs/rowboat](https://github.com/rowboatlabs/rowboat/). This page provides more context about the installation process and the different components involved. - -## Overview - -RowBoat's codebase has three main components: - -| Component | Description | -|--------------|---------------| -| **Agents** | Python framework responsible for carrying out multi-agent conversations | -| **Copilot** | Python framework powering the copilot in RowBoat Studio | -| **RowBoat** | Frontend and backend services to power RowBoat Studio and Chat APIs | - -These components are structured as separate services, each containerized with Docker. Running `docker-compose up --build` enables you to use the Studio in your browser, as well as stands up the APIs and SDK. - -## Prerequisites -All of these prerequistes have open-source or free versions. - -| Prerequisite | Description | -|--------------|---------------| -| **Docker** | Bundles and builds all services | -| **OpenAI API Key** | Agents and Copilot services are powered by OpenAI LLMs | -| **MongoDB** | Stores workflow versions, chats and RAG embeddings | -| **Auth0 Account** | Handles user authentication and identity management for Studio | - -Refer to our [Github Readme for Prerequisites](https://github.com/rowboatlabs/rowboat/?tab=readme-ov-file#prerequisites) to set up prerequisites. - -## Setting up - -Refer to our [Github Readme for Local Development](https://github.com/rowboatlabs/rowboat/?tab=readme-ov-file#local-development-setup) to set up Studio, Chat API and SDK via `docker-compose`. - -### Testing Studio - -1. Once you are set up, you should be able to login to the Studio (default local URL: [http://localhost:3000](http://localhost:8000)) via Auth0's login options (Gmail, Github etc.) -
- -2. Once in Studio, create a new blank project or use one of the example templates: -![Create Project](img/project-page.png) -
- -3. Use the copilot to help you build agents: -![Use Copilot](img/use-copilot.png) -
- -4. Ensure that the correct agent is set as the "start agent": -![Set Start Agent](img/start-agent.png) -
- -5. Test out a chat in the playground to verify the agents' behavior: -![Testing Chat](img/testing-chat.png) -
- -### Testing the Chat API - -You can use the API directly at [http://localhost:3000/api/v1/](http://localhost:3000/api/v1/) -- Project ID is available in the URL of the project page -- API Key can be generated from the project config page at `/projects//config` - -Below is an example request and response. Modify the user message in the request, based on your example project. - -**Request:** - -```bash -curl --location 'http://localhost:3000/api/v1//chat' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Bearer ' \ ---data '{ - "messages": [ - { - "role": "user", - "content": "What is my pending payment amount?" - } - ] -}' -``` -**Response:** -The last message in `messages` is either a user-facing response or a tool call by the assistant. - -```json -{ - "messages": [ - { - "sender": "Credit Card Hub", - "role": "assistant", - "response_type": "internal", - "content": null, - "created_at": "2025-02-01T06:55:47.843909", - "current_turn": true, - "tool_calls": [ - { - "function": { - "arguments": "{\"args\":\"\",\"kwargs\":\"\"}", - // Internal tool calls are used to transfer between agents - "name": "transfer_to_outstanding_payment" - }, - "id": "call_7jGpwpVvzhZFOyRgxHFkdOdU", - "type": "function" - } - ] - }, - { - "tool_name": "transfer_to_outstanding_payment", - "role": "tool", - "content": "{\"assistant\": \"Outstanding Payment\"}", - "tool_call_id": "call_7jGpwpVvzhZFOyRgxHFkdOdU" - }, - { - "sender": "Outstanding Payment", - "role": "assistant", - // Response is not user-facing, to enable further post processing - "response_type": "internal", - "content": "Sure, could you provide the last four digits of your card or your registered mobile number so I can look up your pending payment amount?", - "created_at": "2025-02-01T06:55:49.648008", - "current_turn": true - }, - { - "sender": "Outstanding Payment >> Post process", - "role": "assistant", - // Response is user-facing - "response_type": "external", - "content": "Sure, please provide the last four digits of your card or your registered mobile number so I can check your pending payment amount.", - "created_at": "2025-02-01T06:55:49.648008", - "current_turn": true - } - ], - "state": { - // .. state data - } -} -``` - -### Testing the Python Chat SDK - -```bash -pip install rowboat -``` - -Modify the user message in `messages`, based on your example project. - -```python -from rowboat import Client - -client = Client( - host="http://localhost:3000", - project_id="", - api_key="" # Generate this from /projects//config -) - -# Simple chat interaction -messages = [{"role": "user", "content": "What is my pending payment amount?"}] -response_messages, state = client.chat(messages=messages) -``` -The last message in `response_messages` is either a user-facing response or a tool call by the assistant. \ No newline at end of file diff --git a/apps/docs/docs/img/Intro-Video.gif b/apps/docs/docs/img/Intro-Video.gif new file mode 100644 index 000000000..d4eb387ef Binary files /dev/null and b/apps/docs/docs/img/Intro-Video.gif differ diff --git a/apps/docs/docs/img/add-mcp-server.png b/apps/docs/docs/img/add-mcp-server.png deleted file mode 100644 index 18b629dfb..000000000 Binary files a/apps/docs/docs/img/add-mcp-server.png and /dev/null differ diff --git a/apps/docs/docs/img/add-tool.png b/apps/docs/docs/img/add-tool.png deleted file mode 100644 index 8e85f40f4..000000000 Binary files a/apps/docs/docs/img/add-tool.png and /dev/null differ diff --git a/apps/docs/docs/img/agent-config.png b/apps/docs/docs/img/agent-config.png deleted file mode 100644 index 3887294bd..000000000 Binary files a/apps/docs/docs/img/agent-config.png and /dev/null differ diff --git a/apps/docs/docs/img/chat-delivery.png b/apps/docs/docs/img/chat-delivery.png deleted file mode 100644 index b20dd3694..000000000 Binary files a/apps/docs/docs/img/chat-delivery.png and /dev/null differ diff --git a/apps/docs/docs/img/contribution-guide-hero.png b/apps/docs/docs/img/contribution-guide-hero.png new file mode 100644 index 000000000..705f1a1d7 Binary files /dev/null and b/apps/docs/docs/img/contribution-guide-hero.png differ diff --git a/apps/docs/docs/img/conversations-inside-run.png b/apps/docs/docs/img/conversations-inside-run.png new file mode 100644 index 000000000..540474a6b Binary files /dev/null and b/apps/docs/docs/img/conversations-inside-run.png differ diff --git a/apps/docs/docs/img/conversations-ui.png b/apps/docs/docs/img/conversations-ui.png new file mode 100644 index 000000000..1ab34a855 Binary files /dev/null and b/apps/docs/docs/img/conversations-ui.png differ diff --git a/apps/docs/docs/img/copilot-clarifications.png b/apps/docs/docs/img/copilot-clarifications.png deleted file mode 100644 index 4611015d4..000000000 Binary files a/apps/docs/docs/img/copilot-clarifications.png and /dev/null differ diff --git a/apps/docs/docs/img/copilot-create.png b/apps/docs/docs/img/copilot-create.png deleted file mode 100644 index cf373956a..000000000 Binary files a/apps/docs/docs/img/copilot-create.png and /dev/null differ diff --git a/apps/docs/docs/img/debug-tool-calls.png b/apps/docs/docs/img/debug-tool-calls.png deleted file mode 100644 index aa0e5dd90..000000000 Binary files a/apps/docs/docs/img/debug-tool-calls.png and /dev/null differ diff --git a/apps/docs/docs/img/edit-agent-manually.png b/apps/docs/docs/img/edit-agent-manually.png deleted file mode 100644 index 9c1c679c5..000000000 Binary files a/apps/docs/docs/img/edit-agent-manually.png and /dev/null differ diff --git a/apps/docs/docs/img/enable-mcp-server.png b/apps/docs/docs/img/enable-mcp-server.png deleted file mode 100644 index b7138ebc4..000000000 Binary files a/apps/docs/docs/img/enable-mcp-server.png and /dev/null differ diff --git a/apps/docs/docs/img/example-tool.png b/apps/docs/docs/img/example-tool.png deleted file mode 100644 index 851bbb040..000000000 Binary files a/apps/docs/docs/img/example-tool.png and /dev/null differ diff --git a/apps/docs/docs/img/hub-config.png b/apps/docs/docs/img/hub-config.png deleted file mode 100644 index 0d2c64675..000000000 Binary files a/apps/docs/docs/img/hub-config.png and /dev/null differ diff --git a/apps/docs/docs/img/import-mcp-tools.png b/apps/docs/docs/img/import-mcp-tools.png deleted file mode 100644 index e2c2efff3..000000000 Binary files a/apps/docs/docs/img/import-mcp-tools.png and /dev/null differ diff --git a/apps/docs/docs/img/inspect-agent-tool-connections.png b/apps/docs/docs/img/inspect-agent-tool-connections.png deleted file mode 100644 index 330466b0b..000000000 Binary files a/apps/docs/docs/img/inspect-agent-tool-connections.png and /dev/null differ diff --git a/apps/docs/docs/img/inspect-agent-tools.png b/apps/docs/docs/img/inspect-agent-tools.png deleted file mode 100644 index d5b7cd408..000000000 Binary files a/apps/docs/docs/img/inspect-agent-tools.png and /dev/null differ diff --git a/apps/docs/docs/img/jobs-inside-run.png b/apps/docs/docs/img/jobs-inside-run.png new file mode 100644 index 000000000..ed7d39a81 Binary files /dev/null and b/apps/docs/docs/img/jobs-inside-run.png differ diff --git a/apps/docs/docs/img/jobs-ui.png b/apps/docs/docs/img/jobs-ui.png new file mode 100644 index 000000000..9dd2662fa Binary files /dev/null and b/apps/docs/docs/img/jobs-ui.png differ diff --git a/apps/docs/docs/img/mcp-library.png b/apps/docs/docs/img/mcp-library.png deleted file mode 100644 index 970193f60..000000000 Binary files a/apps/docs/docs/img/mcp-library.png and /dev/null differ diff --git a/apps/docs/docs/img/mcp-tools-build-view.png b/apps/docs/docs/img/mcp-tools-build-view.png deleted file mode 100644 index 30d1f2cdb..000000000 Binary files a/apps/docs/docs/img/mcp-tools-build-view.png and /dev/null differ diff --git a/apps/docs/docs/img/mock-response.png b/apps/docs/docs/img/mock-response.png deleted file mode 100644 index 3f3b68c72..000000000 Binary files a/apps/docs/docs/img/mock-response.png and /dev/null differ diff --git a/apps/docs/docs/img/mock-tool-responses.png b/apps/docs/docs/img/mock-tool-responses.png deleted file mode 100644 index 6ac3d4e27..000000000 Binary files a/apps/docs/docs/img/mock-tool-responses.png and /dev/null differ diff --git a/apps/docs/docs/img/mock-tool.png b/apps/docs/docs/img/mock-tool.png deleted file mode 100644 index ab3c492fb..000000000 Binary files a/apps/docs/docs/img/mock-tool.png and /dev/null differ diff --git a/apps/docs/docs/img/project-page.png b/apps/docs/docs/img/project-page.png deleted file mode 100644 index 61ce2c9e1..000000000 Binary files a/apps/docs/docs/img/project-page.png and /dev/null differ diff --git a/apps/docs/docs/img/rag-adding-data.png b/apps/docs/docs/img/rag-adding-data.png new file mode 100644 index 000000000..675d77a6c Binary files /dev/null and b/apps/docs/docs/img/rag-adding-data.png differ diff --git a/apps/docs/docs/img/re-test-chat.png b/apps/docs/docs/img/re-test-chat.png deleted file mode 100644 index 9d887a658..000000000 Binary files a/apps/docs/docs/img/re-test-chat.png and /dev/null differ diff --git a/apps/docs/docs/img/scenarios.png b/apps/docs/docs/img/scenarios.png deleted file mode 100644 index 828b408b2..000000000 Binary files a/apps/docs/docs/img/scenarios.png and /dev/null differ diff --git a/apps/docs/docs/img/simulate.png b/apps/docs/docs/img/simulate.png deleted file mode 100644 index e6aca1493..000000000 Binary files a/apps/docs/docs/img/simulate.png and /dev/null differ diff --git a/apps/docs/docs/img/start-agent.png b/apps/docs/docs/img/start-agent.png deleted file mode 100644 index 9100fab77..000000000 Binary files a/apps/docs/docs/img/start-agent.png and /dev/null differ diff --git a/apps/docs/docs/img/sys-msg.png b/apps/docs/docs/img/sys-msg.png deleted file mode 100644 index 2a2abfbaa..000000000 Binary files a/apps/docs/docs/img/sys-msg.png and /dev/null differ diff --git a/apps/docs/docs/img/test-updated-agent.png b/apps/docs/docs/img/test-updated-agent.png deleted file mode 100644 index 4bc09d809..000000000 Binary files a/apps/docs/docs/img/test-updated-agent.png and /dev/null differ diff --git a/apps/docs/docs/img/testing-chat.png b/apps/docs/docs/img/testing-chat.png deleted file mode 100644 index 2f2eef549..000000000 Binary files a/apps/docs/docs/img/testing-chat.png and /dev/null differ diff --git a/apps/docs/docs/img/tools-ui.png b/apps/docs/docs/img/tools-ui.png new file mode 100644 index 000000000..b9283d22b Binary files /dev/null and b/apps/docs/docs/img/tools-ui.png differ diff --git a/apps/docs/docs/img/triggers-external-ui.png b/apps/docs/docs/img/triggers-external-ui.png new file mode 100644 index 000000000..e3057ae1d Binary files /dev/null and b/apps/docs/docs/img/triggers-external-ui.png differ diff --git a/apps/docs/docs/img/triggers-onetime-ui.png b/apps/docs/docs/img/triggers-onetime-ui.png new file mode 100644 index 000000000..d38ca558f Binary files /dev/null and b/apps/docs/docs/img/triggers-onetime-ui.png differ diff --git a/apps/docs/docs/img/triggers-recurring-ui.png b/apps/docs/docs/img/triggers-recurring-ui.png new file mode 100644 index 000000000..6fd5ee26c Binary files /dev/null and b/apps/docs/docs/img/triggers-recurring-ui.png differ diff --git a/apps/docs/docs/img/try-chat.png b/apps/docs/docs/img/try-chat.png deleted file mode 100644 index e48520b5f..000000000 Binary files a/apps/docs/docs/img/try-chat.png and /dev/null differ diff --git a/apps/docs/docs/img/update-agent-generate.png b/apps/docs/docs/img/update-agent-generate.png deleted file mode 100644 index 6e076405b..000000000 Binary files a/apps/docs/docs/img/update-agent-generate.png and /dev/null differ diff --git a/apps/docs/docs/img/update-agent-with-copilot.png b/apps/docs/docs/img/update-agent-with-copilot.png deleted file mode 100644 index cfa9b514c..000000000 Binary files a/apps/docs/docs/img/update-agent-with-copilot.png and /dev/null differ diff --git a/apps/docs/docs/img/update-agent.png b/apps/docs/docs/img/update-agent.png deleted file mode 100644 index 05af2ec6b..000000000 Binary files a/apps/docs/docs/img/update-agent.png and /dev/null differ diff --git a/apps/docs/docs/img/use-copilot.png b/apps/docs/docs/img/use-copilot.png deleted file mode 100644 index b48c60405..000000000 Binary files a/apps/docs/docs/img/use-copilot.png and /dev/null differ diff --git a/apps/docs/docs/index.md b/apps/docs/docs/index.md deleted file mode 100644 index 89626228f..000000000 --- a/apps/docs/docs/index.md +++ /dev/null @@ -1,53 +0,0 @@ -# Welcome to Rowboat - -Rowboat is a low-code AI IDE to build MCP tools connected multi-agent assistants. Rowboat copilot builds the agents for you based on your requirements with the option do everything manually as well. - -**Note:** These docs are intended for developers who would like to use our [open-source code](https://github.com/rowboatlabs/rowboat/). - -- Our source code is on GitHub at [@rowboatlabs/rowboat](https://github.com/rowboatlabs/rowboat/) -- Join us on [discord](https://discord.gg/jHhUKkKHn8) -- Email us at [founders@rowboatlabs.com](mailto:founders@rowboatlabs.com) -- Visit our [website](https://www.rowboatlabs.com/) - -## What is RowBoat? -**RowBoat is a state-of-art platform to build multi-agent AI systems in a visual interface, with the help of a copilot.** - -RowBoat enables you to build, manage and deploy user-facing assistants. An assistant is made up of multiple agents, each having access to a set of tools and working together to interact with the user as a single assistant. You can connect any MCP tools to the agents. - -For example, you can build a *credit card assistant*, where each agent handles a workflow such as *outstanding payments*, *balance inquiries* and *transaction disputes*. You can equip agents with tools to carry out tasks such as *fetching payment options*, *checking outstanding balance* and *updating user information*. The assistant would help your end-users their credit card-related needs without having to talk to a human agent on your end. - -## How RowBoat works - -### RowBoat Studio -RowBoat Studio lets you create AI agents in minutes, using a visual interface and plain language. Here are key components that you will work with: - -| Component | Description | Highlights | -|------------|-------------|------------| -| Agent | Handles a specific part of the conversation and
performs tasks using tools, based on instructions |β€’ Configurable using plain language instructions
β€’ Orchestrate between agents connected as a graph
β€’ Can access tools and knowledge sources (RAG)| -| Playground | Interactive environment to test assistants
conversationally as you build them |β€’ Real-time testing and debugging
β€’ Inspect parameters and results of tool calls in-line
β€’ Converse with individual agents or the entire assistant| -| Copilot | AI-powered concierge that creates and
updates agents and tools on your behalf |β€’ Context-aware of all components including playground
β€’ Improves agents based on conversations and feedback
β€’ Understands your requests in plain language| - -### RowBoat Chat API & SDK -- [RowBoat Chat API](/using_the_api) is a stateless HTTP API to interface with the assistant created on RowBoat Studio. You can use the API to drive end-user facing conversations in your app or website. -- [RowBoat Chat SDK](/using_the_sdk) is a simple SDK (currently available in Python) which wraps the HTTP API under the hood. It offers both stateful and stateless (OpenAI-style) implementations. - -### Steps -**RowBoat Studio:** - -1. Describe the assistant you are looking to build, to **copilot** -2. Review and apply the **agents** (and tools) created by copilot -3. Configure **MCP servers** and **tools** and connect them to agents -4. Chat with your assistant in the **playground** -6. Deploy and use the HTTP API or Python SDK to integrate the agents into your system - -## Why RowBoat? -Rowboat is the fastest way to build and deploy MCP connected multi-agents - -1. **Build** complex assistants using plain language and a visual interface -2. **Integrate** tools and MCP servers in minutes -3. **Expedite** your multi-agent AI roadmap using battle-tested tooling - -## Getting started - -- To set up our open-source installation, see [Github Readme](https://github.com/rowboatlabs/rowboat) -- To sign up for our managed offering (beta), please email us at [founders@rowboatlabs.com](mailto:founders@rowboatlabs.com) \ No newline at end of file diff --git a/apps/docs/docs/oss_installation.md b/apps/docs/docs/oss_installation.md deleted file mode 100644 index b26c53884..000000000 --- a/apps/docs/docs/oss_installation.md +++ /dev/null @@ -1,32 +0,0 @@ -# Open Source Installation - -- This is the developers guide to self-hosting the open-source version of RowBoat. To get started with the hosted app, please see [Using the Hosted App](/hosted_setup) -- Please see our [Introduction](/) page before referring to this guide. -- For direct installation steps, please head to the README of RowBoat's Github repo: [@rowboatlabs/rowboat](https://github.com/rowboatlabs/rowboat/). This page provides more context about the installation process and the different components involved. - -## Overview - -RowBoat's codebase has three main components: - -| Component | Description | -|--------------|---------------| -| **Agents** | Python framework responsible for carrying out multi-agent conversations | -| **Copilot** | Python framework powering the copilot in RowBoat Studio | -| **RowBoat** | Frontend and backend services to power RowBoat Studio and Chat APIs | - -These components are structured as separate services, each containerized with Docker. Running `docker-compose up --build` enables you to use the Studio in your browser, as well as stands up the APIs and SDK. - -## Prerequisites -All of these prerequisites have open-source or free versions. - -| Prerequisite | Description | -|--------------|---------------| -| **Docker** | Bundles and builds all services | -| **OpenAI API Key** | Agents and Copilot services are powered by OpenAI LLMs | -| **MongoDB** | Stores workflow versions, chats and RAG embeddings | - -Refer to our [Github Readme for Prerequisites](https://github.com/rowboatlabs/rowboat/?tab=readme-ov-file#prerequisites) to set up prerequisites. - -## Setting up - -Refer to our [Github Readme for Local Development](https://github.com/rowboatlabs/rowboat/?tab=readme-ov-file#local-development-setup) to set up Studio, Chat API and SDK via `docker-compose`. \ No newline at end of file diff --git a/apps/docs/docs/playground.md b/apps/docs/docs/playground.md deleted file mode 100644 index 3f1f0590c..000000000 --- a/apps/docs/docs/playground.md +++ /dev/null @@ -1,7 +0,0 @@ -## Try an example chat in the playground - -### Chat with the assistant - -The playground is intended to test out the assistant as you build it. The User and Assistant messages represent the conversation that your end-user will have if your assistant is deployed in production. The playground also has debug elements which show the flow of control between different agents in your system, as well as which agent finally responded to the user. - -![Try Chat](img/chat-delivery.png) \ No newline at end of file diff --git a/apps/docs/docs/prompts.md b/apps/docs/docs/prompts.md deleted file mode 100644 index 2552cc49f..000000000 --- a/apps/docs/docs/prompts.md +++ /dev/null @@ -1,5 +0,0 @@ -# Prompts - -- Prompts are reusable pieces of agent instructions in Studio. -- Prompts can be defined once and reused across multiple agents. -- Common examples of prompts are style prompts which indicate brand voice and structured output prompts which specify a format for the agent to provide its output in (e.g. ReAct) \ No newline at end of file diff --git a/apps/docs/docs/setup.md b/apps/docs/docs/setup.md deleted file mode 100644 index f9ed3ef76..000000000 --- a/apps/docs/docs/setup.md +++ /dev/null @@ -1,127 +0,0 @@ -## Getting started - -- ✨ **Start from an idea β†’ Copilot builds your multi-agent workflows** - E.g. "Build me an assistant for a food delivery company to handle delivery status and missing items. Include the necessary tools." -- 🌐 **Connect MCP servers** - Add the MCP servers in Settings β†’ import the tools into Rowboat. -- πŸ“ž **Integrate into your app using the HTTP API or Python SDK** - Grab the Project ID and generated API Key from Settings and use the API. - -Powered by OpenAI's Agents SDK, Rowboat is the fastest way to build multi-agents! - -## Quick start - -Step 1. Set your OpenAI key: - -```bash -export OPENAI_API_KEY=your-openai-api-key -``` - -Step 2. Clone the repository and start Rowboat docker - -```bash -git clone git@github.com:rowboatlabs/rowboat.git -cd rowboat -docker-compose up --build -``` - -Step 3. Access the app at [http://localhost:3000](http://localhost:3000). - -Note: See the [Using custom LLM providers](#using-custom-llm-providers) section below for using custom providers like OpenRouter and LiteLLM. - -## Demo - -#### Create a multi-agent assistant with MCP tools by chatting with Rowboat -[![Screenshot 2025-04-23 at 00 25 31](https://github.com/user-attachments/assets/c8a41622-8e0e-459f-becb-767503489866)](https://youtu.be/YRTCw9UHRbU) - -## Integrate with Rowboat agents - -There are 2 ways to integrate with the agents you create in Rowboat - -**Option #1: HTTP API** - -You can use the API directly at [http://localhost:3000/api/v1/](http://localhost:3000/api/v1/). See [API Docs](https://docs.rowboatlabs.com/using_the_api/) for details. - -```bash -curl --location 'http://localhost:3000/api/v1//chat' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Bearer ' \ ---data '{ - "messages": [ - { - "role": "user", - "content": "tell me the weather in london in metric units" - } - ], - "state": null -}' -``` - - -**Option #2: Python SDK** - -You can use the included Python SDK to interact with the Agents - -```python -from rowboat import Client, StatefulChat -from rowboat.schema import UserMessage, SystemMessage - -# Initialize the client -client = Client( - host="http://localhost:3000", - project_id="", - api_key="" -) - -# Create a stateful chat session (recommended) -chat = StatefulChat(client) -response = chat.run("What's the weather in London?") -print(response) - -# Or use the low-level client API -messages = [ - SystemMessage(role='system', content="You are a helpful assistant"), - UserMessage(role='user', content="Hello, how are you?") -] - -# Get response -response = client.chat(messages=messages) -print(response.messages[-1].content) -``` - -## Using custom LLM providers -By default, Rowboat uses OpenAI LLMs (gpt-4o, gpt-4.1, etc.) for both agents and copilot, when you export your OPENAI_API_KEY. - -However, you can also configure custom LLM providers (e.g. LiteLLM, OpenRouter) to use any of the hundreds of available LLMs beyond OpenAI, such as Claude, DeepSeek, Ollama LLMs and so on. - -**Step 1:** Set up your custom LLM provider using the variables below, for example (assuming LiteLLM): - -```bash -export PROVIDER_BASE_URL=http://host.docker.internal:4000/ -export PROVIDER_API_KEY=sk-1234 -``` - -Rowboat uses "gpt-4.1" as the default model for agents and copilot but this can be overridden as follows, for example (assuming LiteLLM): - -```bash -export PROVIDER_DEFAULT_MODEL=claude-3-7-sonnet-latest -export PROVIDER_COPILOT_MODEL=gpt-4o -``` - -**Notes:** - -- Copilot is optimized for gpt-4o/gpt-4.1. We strongly recommend using these models for best performance. -- You can specify different models for the copilot and each agent, but all of them must belong to the same provider (e.g. LiteLLM) -- The integration is provider-agnostic and should work with any service that implements the OpenAI messages format. -- OpenAI-specific tools (e.g., web_search) will not work with non-OpenAI providers. If you get an error, remove these tools. - -**Step 2 (No change):** Clone the repository and start Rowboat docker - -```bash -git clone git@github.com:rowboatlabs/rowboat.git -cd rowboat -docker-compose up --build -``` - -**Step 3 (No change):** Access the app at [http://localhost:3000](http://localhost:3000). - diff --git a/apps/docs/docs/simulate.md b/apps/docs/docs/simulate.md deleted file mode 100644 index e488d0d5d..000000000 --- a/apps/docs/docs/simulate.md +++ /dev/null @@ -1,6 +0,0 @@ -## Simulate real-world user scenarios -Create a test-bench of real-world scenarios in the simulator. -![Scenarios](img/scenarios.png) - -Run the scenarios as simulated chats betweeen a user (role-played) and the assistant, in the playground. -![Simulation](img/simulate.png) \ No newline at end of file diff --git a/apps/docs/docs/studio_overview.md b/apps/docs/docs/studio_overview.md deleted file mode 100644 index 89ac4e85b..000000000 --- a/apps/docs/docs/studio_overview.md +++ /dev/null @@ -1,7 +0,0 @@ -# Building Assistants in Studio -This is a guide to building your first assistant on RowBoat Studio, with examples.
- -Prerequisite: - -1. **Open Source Users:** Complete the [open-source installation steps](/oss_installation/) to set up RowBoat Studio. -2. **Hosted App Users:** Sign in to [https://app.rowboatlabs.com/](https://app.rowboatlabs.com/) \ No newline at end of file diff --git a/apps/docs/docs/testing.md b/apps/docs/docs/testing.md deleted file mode 100644 index 86df88be6..000000000 --- a/apps/docs/docs/testing.md +++ /dev/null @@ -1,132 +0,0 @@ -# Testing Your Setup - -## Testing Studio - -1. Once you are set up, you should be able to login to the Studio via Auth0's login options (Gmail, Github etc.). -- For the open source installation, the URL for Studio is [http://localhost:3000](http://localhost:3000) -- To use our hosted app, the URL for Studio is [https://app.rowboatlabs.com](https://app.rowboatlabs.com/) -
- -2. Once in Studio, create a new blank project or browse through one of the example projects: -![Create Project](img/project-page.png) -
- -3. Use the copilot to help you build agents: -![Use Copilot](img/use-copilot.png) -
- -4. Ensure that the correct agent is set as the "start agent": -![Set Start Agent](img/start-agent.png) -
- -5. Test out a chat in the playground to verify the agents' behavior: -![Testing Chat](img/testing-chat.png) -
- -### Testing the Chat API - -- For the open source installation, the `` is [http://localhost:3000](http://localhost:3000) -- When using the hosted app, the `` is [https://app.rowboatlabs.com](https://app.rowboatlabs.com) -- `` is available in the URL of the project page -- API Key can be generated from the project config page at `/projects//config` - -Below is an example request and response. Modify the user message in the request, based on your example project. - -**Request:** - -```bash -curl --location 'http:///api/v1//chat' \ ---header 'Content-Type: application/json' \ ---header 'Authorization: Bearer ' \ ---data '{ - "messages": [ - { - "role": "user", - "content": "What is my pending payment amount?" - } - ] -}' -``` -**Response:** -The last message in `messages` is either a user-facing response or a tool call by the assistant. - -```json -{ - "messages": [ - { - "sender": "Credit Card Hub", - "role": "assistant", - "response_type": "internal", - "content": null, - "created_at": "2025-02-01T06:55:47.843909", - "current_turn": true, - "tool_calls": [ - { - "function": { - "arguments": "{\"args\":\"\",\"kwargs\":\"\"}", - // Internal tool calls are used to transfer between agents - "name": "transfer_to_outstanding_payment" - }, - "id": "call_7jGpwpVvzhZFOyRgxHFkdOdU", - "type": "function" - } - ] - }, - { - "tool_name": "transfer_to_outstanding_payment", - "role": "tool", - "content": "{\"assistant\": \"Outstanding Payment\"}", - "tool_call_id": "call_7jGpwpVvzhZFOyRgxHFkdOdU" - }, - { - "sender": "Outstanding Payment", - "role": "assistant", - // Response is not user-facing, to enable further post processing - "response_type": "internal", - "content": "Sure, could you provide the last four digits of your card or your registered mobile number so I can look up your pending payment amount?", - "created_at": "2025-02-01T06:55:49.648008", - "current_turn": true - }, - { - "sender": "Outstanding Payment >> Post process", - "role": "assistant", - // Response is user-facing - "response_type": "external", - "content": "Sure, please provide the last four digits of your card or your registered mobile number so I can check your pending payment amount.", - "created_at": "2025-02-01T06:55:49.648008", - "current_turn": true - } - ], - "state": { - // .. state data - } -} -``` - -### Testing the Python Chat SDK - -- For the open source installation, the `` is [http://localhost:3000](http://localhost:3000) -- When using the hosted app, the `` is [https://app.rowboatlabs.com](https://app.rowboatlabs.com) -- `` is available in the URL of the project page -- API Key can be generated from the project config page at `/projects//config` - -```bash -pip install rowboat -``` - -Modify the user message in `messages`, based on your example project. - -```python -from rowboat import Client - -client = Client( - host="", - project_id="", - api_key="" # Generate this from /projects//config -) - -# Simple chat interaction -messages = [{"role": "user", "content": "What is my pending payment amount?"}] -response_messages, state = client.chat(messages=messages) -``` -The last message in `response_messages` is either a user-facing response or a tool call by the assistant. \ No newline at end of file diff --git a/apps/docs/docs/tools.md b/apps/docs/docs/tools.md deleted file mode 100644 index 162dad365..000000000 --- a/apps/docs/docs/tools.md +++ /dev/null @@ -1,6 +0,0 @@ -# Tools -- Tools are used to carry out specific tasks such as fetching or updating information. -- Tools can be defined once in RowBoat Studio and reused across different agents. -- RowBoat uses OpenAI style tools with name, description and parameters. -- For the purposes of quick testing in the Playground, RowBoat Studio can mock tool responses based on tool descriptions. -- Developers can easily connect tools to APIs by configuring MCP servers or Webhook URL in Settings. \ No newline at end of file diff --git a/apps/docs/docs/update_agents.md b/apps/docs/docs/update_agents.md deleted file mode 100644 index 10fd437bc..000000000 --- a/apps/docs/docs/update_agents.md +++ /dev/null @@ -1,19 +0,0 @@ -## Update agent behavior - -There are three ways for you to update the agent's behavior: - -### 1. With help of Copilot - -Copilot can help you update agent behavior. It is also aware of the current chat in the playground so you can make references to the current chat while instructing copilot to update agents. - -![Update Agent Behavior](img/update-agent-copilot.png) - -### 2. Using the Generate button - -![Update Agent Behavior](img/update-agent-generate.png) - -### 3. By manually editing the instructions - -You can manually edit the agent instructions anytime. - -![Update Agent Behavior](img/update-agent-manual.png) diff --git a/apps/docs/docs/using-rowboat/agents.mdx b/apps/docs/docs/using-rowboat/agents.mdx new file mode 100644 index 000000000..ceaeccae2 --- /dev/null +++ b/apps/docs/docs/using-rowboat/agents.mdx @@ -0,0 +1,141 @@ +--- +title: "Agents" +description: "Learn about creating and configuring individual agents within your multi-agent system" +icon: "robot" +--- + +## Overview + +Agents are the core building blocks of Rowboat's multi-agent system. Each agent carries out a specific part of a conversation, handles tasks via tools, and can collaborate with other agents to orchestrate complex workflows. + +They are powered by LLMs and can: +- Respond to user input +- Trigger tools or APIs +- Pass control to other agents using @mentions +- Fetch or process internal data +- Execute RAG (Retrieval-Augmented Generation) queries +- Participate in sequential pipeline workflows + +--- + +## Agent Types + +Rowboat supports several types of agents, each designed for specific use cases: + +| Name | Purpose | Characteristics | +|------|---------|-----------------| +| **Conversational Agents** (`conversation`) | Primary user-facing agents that interact directly with users and orchestrate workflows. | β€’ Can respond to users and orchestrate workflows
β€’ Typically serve as the start agent (Hub Agent)| +| **Task Agents** (`internal`) | Specialized agents that perform specific tasks without direct user interaction. | β€’ Focused on specific functions
β€’ Return results to parent agents| +| **Pipeline Agents** (`pipeline`) | Sequential workflow execution agents that process data in a chain. | β€’ Execute in sequence within a pipeline
β€’ Cannot transfer to other agents directly| + + +--- + +## Agent Configuration + +Agents are configured through two main tabs in the Rowboat Studio interface: + +### **Instructions Tab** + + +#### Description +A clear description of the agent's role and responsibilities + +#### Instructions +Instructions are the backbone of the agent's behavior. Use the Copilot's structured format for consistency: + +**Recommended Structure:** +``` +## πŸ§‘β€πŸ’Ό Role: +[Clear description of the agent's role] + +## βš™οΈ Steps to Follow: +1. [Step 1] +2. [Step 2] +3. [Step 3] + +## 🎯 Scope: +βœ… In Scope: +- [What the agent should handle] + +❌ Out of Scope: +- [What the agent should NOT handle] + +## πŸ“‹ Guidelines: +βœ”οΈ Dos: +- [Positive behaviors] + +🚫 Don'ts: +- [Negative behaviors] +``` + +#### Examples +These help agents behave correctly in specific situations. Each example can include: +- A sample user message +- The expected agent response +- Any tool calls (if applicable) + +### **Configurations Tab** + +#### Name +Name of the agent + + +#### Behaviour +- **Agent Type**: Choose from `conversation`, `internal`, or `pipeline` +- **Model**: Select the LLM model (GPT-4.1, GPT-4o, google/gemini-2.5-flash, etc.) + +#### RAG +- **Add Source**: Connect data sources to enable RAG capabilities for the agent + +--- + +## Creating Your Initial Set of Agents + +Let Copilot bootstrap your agent graph. + +### Instruct Copilot + +Start by telling Copilot what your assistant is meant to do β€” it'll generate an initial set of agents with best-practice instructions, role definitions, and connected agents. + + + Creating agents with Copilot + + +### Inspect the Output + +After applying the suggested agents, take a close look at each one's: +- **Instructions**: Define how the agent behaves +- **Examples**: Guide agent responses and tool use + + + Inspect agent instructions + + +--- + +## Updating Agent Behavior + +There are three ways to update an agent: + +### 1. With Copilot + +Copilot understands the current chat context and can help rewrite or improve an agent's behavior based on how it performed. + + + Update agent using Copilot + + + + +### 2. Manual Edits + +You can always manually edit the agent's instructions. + + + Manually edit agent + + +--- + + diff --git a/apps/docs/docs/using-rowboat/conversations.mdx b/apps/docs/docs/using-rowboat/conversations.mdx new file mode 100644 index 000000000..c755f47d2 --- /dev/null +++ b/apps/docs/docs/using-rowboat/conversations.mdx @@ -0,0 +1,52 @@ +--- +title: "Conversations" +description: "View and manage all conversations with your Rowboat agents" +icon: "list-check" +--- + +## Overview + +The Conversations page in Rowboat shows you all the interactions between users and your agents. Here you can monitor conversations, view detailed message exchanges, and understand how your agents are performing. + + + Conversations page UI showing list of conversations + + +## What You'll See + +The Conversations page displays a list of all conversations organized by time: + +- **Today**: Recent conversations from today +- **This week**: Conversations from the current week +- **This month**: Conversations from the current month +- **Older**: Conversations from previous months + +Each conversation shows: +- **Conversation ID**: Unique identifier for the conversation +- **Created time**: When the conversation started +- **Reason**: What triggered the conversation (chat or job) + +## Viewing Conversation Details +Click on any conversation to see the detailed view with all the message exchanges: + + + Conversation details showing expanded view of a conversation with turns and messages + + +**Conversation Metadata**: Shows the Conversation ID, creation time, and last update time. + +**Workflow**: Shows the workflow JSON + +**Turns**: Each conversation is made up of turns, where: +- **Turn #1, #2, etc.**: Numbered sequence of interactions +- **Reason badge**: Shows why each turn happened (chat, API, job, etc.) +- **Timestamp**: When each turn occurred +- **Input messages**: What was sent to your agents +- **Output messages**: What your agents responded with + +### Turn Details + +Each turn displays: +- **Input**: The messages sent to your agents (user messages, system messages) +- **Output**: The responses from your agents +- **Error information**: Any issues that occurred during processing diff --git a/apps/docs/docs/using-rowboat/customise/custom-llms.mdx b/apps/docs/docs/using-rowboat/customise/custom-llms.mdx new file mode 100644 index 000000000..64b27ca15 --- /dev/null +++ b/apps/docs/docs/using-rowboat/customise/custom-llms.mdx @@ -0,0 +1,53 @@ +--- +title: "Custom LLMs" +description: "How to use and configure custom LLMs in Rowboat." + +--- + + This is currently only possible in the self hosted version of Rowboat + +## Using custom LLM providers + +By default, Rowboat uses OpenAI LLMs (gpt-4o, gpt-4.1, etc.) for both agents and copilot, when you export your OPENAI_API_KEY. + +However, you can also configure custom LLM providers (e.g. LiteLLM, OpenRouter) to use any of the hundreds of available LLMs beyond OpenAI, such as Claude, DeepSeek, Ollama LLMs and so on. + + + + Configure your environment variables to point to your preferred LLM backend. Example using LiteLLM: + + ```bash + export PROVIDER_BASE_URL=http://host.docker.internal:4000/ + export PROVIDER_API_KEY=sk-1234 + ``` + + Rowboat uses gpt-4.1 as the default model for agents and copilot. You can override these: + + ```bash + export PROVIDER_DEFAULT_MODEL=claude-3-7-sonnet-latest + export PROVIDER_COPILOT_MODEL=gpt-4.1 + ``` + + **Notes:** + - Copilot is optimized for gpt-4o/gpt-4.1. We strongly recommend using these models for best results. + - You can use different models for the copilot and each agent, but all must be from the same provider (e.g., LiteLLM). + - Rowboat is provider-agnostic β€” any backend implementing the OpenAI messages format should work. + - OpenAI-specific tools (like web_search) will not function with non-OpenAI providers. Remove such tools to avoid errors. + + + + Clone the Rowboat repo and spin it up locally: + + ```bash + git clone git@github.com:rowboatlabs/rowboat.git + cd rowboat + docker-compose up --build + ``` + + + + Once Docker is running, navigate to: + + [http://localhost:3000](http://localhost:3000) + + diff --git a/apps/docs/docs/using-rowboat/jobs.mdx b/apps/docs/docs/using-rowboat/jobs.mdx new file mode 100644 index 000000000..5b3e14dfd --- /dev/null +++ b/apps/docs/docs/using-rowboat/jobs.mdx @@ -0,0 +1,45 @@ +--- +title: "Jobs" +description: "Monitor and inspect all your trigger executions and job runs" +icon: "message" +--- + +## Overview + +The Jobs page in Rowboat provides a comprehensive view of all your automated job executions. Here you can monitor the status of your triggers, inspect what happened during each run, and troubleshoot any issues that may have occurred. + + + Jobs page showing list of all job runs with status indicators + + +## What You'll See + +The Jobs page displays a list of all job runs from your triggers, including: + +- **External trigger executions** from webhook events +- **One-time trigger runs** from scheduled jobs +- **Recurring trigger executions** from cron-based schedules + +Each job run displays the following key information: +- **Job ID**: Unique identifier for the job run +- **Status**: Indicates if the job succeeded, failed, or is in progress +- **Reason**: The trigger or cause for the job (e.g., external trigger, scheduled, cron) +- **Created Time**: When the job was executed + +## Viewing Job Details + +### Expand a Job Run + +Click on any job run to expand it and see detailed information about what happened during execution: + + + Job run details showing expanded information for a specific job + + +**Basic job details**: Job ID, Status, creation time, Updated time, Conversation ID and Turn ID. By clicking on the Conversation ID, you can view more in-depth details about the run. + +**Job Reason**: Why the job triggered - either external trigger, scheduled, or cron. + +**Job Input**: The input data sent to your assistant. + +**Job Output**: The final output produced by your agents. \ No newline at end of file diff --git a/apps/docs/docs/using-rowboat/rag.mdx b/apps/docs/docs/using-rowboat/rag.mdx new file mode 100644 index 000000000..772d034d5 --- /dev/null +++ b/apps/docs/docs/using-rowboat/rag.mdx @@ -0,0 +1,68 @@ +--- +title: "RAG (Data)" +description: "How to use our inbuilt RAG" +icon: "database" +--- + +# Using RAG in Rowboat + +Rowboat provides multiple ways to enhance your agents' context with Retrieval-Augmented Generation (RAG). This guide will help you set up and use each RAG feature. + +RAG is called "Data" on the build view in the Rowboat UI. + +--- + +## Types of RAG + +| RAG Type | Description | Configuration Required | +|----------|-------------|------------------------| +| **Text RAG** | Process and reason over text content directly | No configuration needed | +| **File Uploads** | Upload PDF files directly from your device | No configuration needed | +| **URL Scraping** | Scrape content from web URLs using Firecrawl | Requires API key setup | + + URL Scraping does not require any setup in the managed version of Rowboat. + + + Adding data sources for RAG in Rowboat + + + +## RAG Features + +### 1. Text RAG + +Process and reason over text content directly + + +### 2. File Uploads + +- Upload PDF files directly from your device +- **Open Source Version**: Files are stored locally on your machine +- **Managed Version**: Files are stored in cloud S3 storage +- Files are parsed using OpenAI by default + + You can also use Google's Gemini model for parsing as it is better at parsing larger files. + +#### 2.1 Using Gemini for File Parsing + +To use Google's Gemini model for parsing uploaded PDFs, set the following variables: + +```bash +# Enable Gemini for file parsing +export USE_GEMINI_FILE_PARSING=true +export GOOGLE_API_KEY=your_google_api_key +``` + + +### 3. URL Scraping + +Rowboat uses Firecrawl for URL scraping. You can have a maximum of 100 URLs. + +**Open Source Version**: To enable URL scraping, set the following variables: + +```bash +export USE_RAG_SCRAPING=true +export FIRECRAWL_API_KEY=your_firecrawl_api_key +``` + +**Managed Version**: No configuration required - URL scraping is handled automatically. diff --git a/apps/docs/docs/using-rowboat/rowboat-studio.mdx b/apps/docs/docs/using-rowboat/rowboat-studio.mdx new file mode 100644 index 000000000..edf74fb3e --- /dev/null +++ b/apps/docs/docs/using-rowboat/rowboat-studio.mdx @@ -0,0 +1,60 @@ +--- +title: "Rowboat Studio" +description: "Visual interface to build, test, and deploy multi-agent AI assistants using plain language" +icon: "puzzle-piece" +--- + + +## Overview + +**Rowboat Studio** is your visual interface for building AI assistants β€” powered by agents, tools, and workflows β€” using plain language and minimal setup. It brings the process of creating multi-agent systems down to just a few clicks. + +Workflows created within Rowboat are known as **assistants**, and each assistant is composed of: +- One or more **agents** +- Attached **tools** and **MCP servers** + +Once built, assistants can be tested live in the **playground** and deployed in real-world products using the [API](/docs/api-sdk/using_the_api) or [SDK](/docs/api-sdk//using_the_sdk). + +--- + +## Key Components + +Here’s what you’ll interact with in Studio: + +| Component | Description | Highlights | +|------------|-------------|------------| +| **Agent** | Core building blocks of your assistant.
Each agent handles a specific part of the conversation and performs tasks using tools and instructions. | β€’ Define behavior in plain language
β€’ Connect agents into a graph
β€’ Attach tools and RAG sources | +| **Playground** | Interactive testbed for conversations.
Lets you simulate end-user chats with your assistant and inspect agent behavior in real time. | β€’ Real-time feedback and debugging
β€’ See tool calls and agent handoffs
β€’ Test individual agents or the whole system | +| **Copilot** | Your AI assistant for building assistants.
Copilot creates and updates agents, tools, and instructions based on your plain-English prompts. | β€’ Understands full system context
β€’ Improves agents based on playground chat
β€’ Builds workflows intelligently and fast | + +> **Agents are the heart of every assistant.** Learn more about how they work in the Agents page. + + + Learn about creating and configuring individual agents within your multi-agent system + +--- + +## Building in Rowboat + + + + Use plain language to tell Copilot what you want your assistant to do. Copilot will auto-generate the agents, instructions, and tools that form the base of your assistant. + + + + Inspect the created agents β€” especially their instructions and examples β€” and refine or approve them before moving forward. + + + + Integrate external services, tools, and backend logic into your agents using Rowboat's modular system. Tools are tied to agents and triggered through instructions. + + + + Use the chat playground to simulate real-world conversations. You’ll see which agent takes control, what tools are triggered, and how your assistant flows. + + + + Assistants can be deployed into production using the **Rowboat Chat API** or the **Rowboat Chat SDK**. Both support stateless and stateful conversation flows. + + + diff --git a/apps/docs/docs/using-rowboat/tools.mdx b/apps/docs/docs/using-rowboat/tools.mdx new file mode 100644 index 000000000..7a116d634 --- /dev/null +++ b/apps/docs/docs/using-rowboat/tools.mdx @@ -0,0 +1,56 @@ +--- +title: "Tools" +description: "Add and configure tools for your agents to interact with external services" +icon: "wrench" +--- + +## Overview + +The Tools page in Rowboat lets you add and configure tools that your agents can use to interact with external services, APIs, and systems. Tools enable your agents to perform real-world actions like sending emails, managing calendars, or processing payments. + + + Screenshot of the Tools UI in Rowboat + + +## Tool Types + +| Tool Type | Description | Use Case | Availability | +|-----------|-------------|----------|--------------| +| **Library Tools** | Pre-built integrations with popular services | Quick setup, no configuration needed | Managed and open source | +| **MCP Tools** | Custom tools from MCP servers | Custom functionality, specialized APIs | Managed and open source | +| **Webhook Tools** | HTTP endpoints for custom integrations | Your own systems, custom workflows | Open source only | + + +## Library (Composio Tools) + +- Browse a library of 500+ toolkits from popular services +- With 3000+ tools to choose from! +- Click on a service to see available tools and add them to your workflow +- Users must create a [Composio](https://composio.dev/) account and add their API key +- Tools require authorization to work properly + +### Setting up Composio API Key + +To use Composio tools, get a Composio key and export it as an environment variable: + +```bash +export COMPOSIO_API_KEY=your_api_key_here +``` + +Users can visit [Composio's toolkit documentation](https://docs.composio.dev/toolkits/introduction) for a deep dive into all the tools available. + +## Custom MCP Servers + +- Add your own MCP (Model Context Protocol) servers +- Connect to custom tools and APIs you've built +- Configure server URLs and authentication +- Import tools from your MCP servers + +## Webhook + +Webhook tools are only available in the open source (local) version of Rowboat. + +- Create custom webhook tools +- Configure HTTP endpoints for your agents to call +- Set up custom authentication and parameters +- Build integrations with your own systems diff --git a/apps/docs/docs/using-rowboat/triggers.mdx b/apps/docs/docs/using-rowboat/triggers.mdx new file mode 100644 index 000000000..32c81f66d --- /dev/null +++ b/apps/docs/docs/using-rowboat/triggers.mdx @@ -0,0 +1,131 @@ +--- +title: "Triggers" +description: "Learn about setting up automated triggers for your Rowboat agents" +icon: "bolt" +--- + +## Overview + +Triggers in Rowboat are automated mechanisms that activate your agents when specific events occur or conditions are met. They form the foundation of your automated workflow system, enabling your agents to respond to external events, scheduled times, and system conditions without manual intervention. + + + +## Trigger Types + +Rowboat supports three main categories of triggers, each designed for different automation scenarios: + +| Trigger Type | Purpose | Execution | Use Cases | +|--------------|---------|-----------|-----------| +| **External Triggers** | Connect to external services and events | Real-time via webhooks | Slack messages, GitHub events, email processing | +| **One-Time Triggers** | Execute at specific predetermined times | Single execution at set time | Delayed responses, time-sensitive actions | +| **Recurring Triggers** | Execute on repeating schedules | Continuous via cron expressions | Daily reports, periodic maintenance, regular syncs | + +--- + +## External Triggers (Composio Integration) + +External triggers are powered by **Composio** and allow users to use triggers from across 30+ services including Slack, GitHub, Gmail, Notion, Google Calendar, and more. + + + External Triggers UI showing available toolkits and services + + +### Creating External Triggers + +1. **Click New External Trigger**: Start the trigger creation process +2. **Select a Toolkit**: Browse available toolkits or search for specific services +3. **Choose Trigger Type**: Select the specific trigger from available options, click configure +4. **Authenticate**: Complete OAuth2 flow or enter API keys for the selected service (your preferred method) +5. **Configure**: Set up event filters and data mapping if required +6. **Deploy**: Activate the trigger to start listening for events + +### Local Setup + +If you're running the open source version of Rowboat, you'll need to set up external triggers manually. In the managed version, this is all handled automatically for you. + + + + Sign into [Composio](https://composio.dev/) and create a new project for your Rowboat instance. + + + + Go to your project settings and copy the project API key. Export it in your Rowboat environment: + + ```bash + export COMPOSIO_API_KEY=your-composio-api-key + ``` + + + + Use ngrok to expose your local Rowboat instance: + + ```bash + ngrok http 3000 + ``` + + Copy the generated ngrok URL (e.g., `https://a5fe8c0d45b8.ngrok-free.app`). + + + + In Composio, go to Events & Triggers section and set the Trigger Webhook URL to: + + ``` + {ngrok_url}/api/composio/webhook + ``` + + Example: `https://a5fe8c0d45b8.ngrok-free.app/api/composio/webhook` + + + + Copy the Webhook Secret from Composio and export it in Rowboat: + + ```bash + export COMPOSIO_TRIGGERS_WEBHOOK_SECRET=your-webhook-secret + ``` + + + + Restart your Rowboat instance to load the new environment variables. You're now ready to use external triggers! + + + +Make sure your Rowboat assistant is deployed before receiving trigger calls + +--- + +## One-Time Triggers (Scheduled Jobs) + +One-time triggers execute your agents at a specific, predetermined time. They're useful for delayed responses, batch processing, time-sensitive actions, or coordinating with external schedules. + + + One-Time Triggers UI showing scheduled job configuration + + +### Creating One-Time Triggers +1. Set the exact execution time (date and time) +2. Configure the input messages for your agents +3. Deploy to schedule the execution + +--- + +## Recurring Triggers (Cron-based Jobs) + +Recurring triggers execute your agents on a repeating schedule using cron expressions. They're ideal for daily reports, periodic maintenance, regular data syncs, and continuous monitoring tasks. + + + Recurring Triggers UI showing cron-based job configuration + + +### Creating Recurring Triggers +1. Define the cron expression (e.g., `0 9 * * *` for daily at 9 AM) +2. Configure the recurring message structure +3. Enable the trigger to start the recurring schedule + +### Common Cron Patterns +```cron +0 9 * * * # Daily at 9:00 AM +0 8 * * 1 # Every Monday at 8:00 AM +*/15 * * * * # Every 15 minutes +0 0 1 * * # First day of month at midnight +``` + diff --git a/apps/docs/docs/using_rag.md b/apps/docs/docs/using_rag.md deleted file mode 100644 index 52deefadf..000000000 --- a/apps/docs/docs/using_rag.md +++ /dev/null @@ -1,103 +0,0 @@ -# Using RAG in Rowboat - -Rowboat provides multiple ways to enhance your agents' context with Retrieval-Augmented Generation (RAG). This guide will help you set up and use each RAG features. - -## Quick Start - -Text RAG and local file uploads are enabled by default - no configuration needed! Just start using them right away. - -## RAG Features - -### 1. Text RAG -βœ… Enabled by default: - -- Process and reason over text content directly -- No configuration required - -### 2. Local File Uploads -βœ… Enabled by default: - -- Upload PDF files directly from your device -- Files are stored locally -- No configuration required -- Files are parsed using OpenAI by default -- For larger files, we recommend using Gemini models - see section below. - -#### 2.1 Using Gemini for File Parsing -To use Google's Gemini model for parsing uploaded PDFs, set the following variable: - -```bash -# Enable Gemini for file parsing -export USE_GEMINI_FILE_PARSING=true -export GOOGLE_API_KEY=your_google_api_key -``` - -### 3. URL Scraping -Rowboat uses Firecrawl for URL scraping. To enable URL scraping, set the following variables: - -```bash -export USE_RAG_SCRAPING=true -export FIRECRAWL_API_KEY=your_firecrawl_api_key -``` - -## Advanced RAG features - -### 1. File Uploads Backed by S3 -To enable S3 file uploads, set the following variables: - -```bash -# Enable S3 uploads -export USE_RAG_S3_UPLOADS=true - -# S3 Configuration -export AWS_ACCESS_KEY_ID=your_access_key -export AWS_SECRET_ACCESS_KEY=your_secret_key -export RAG_UPLOADS_S3_BUCKET=your_bucket_name -export RAG_UPLOADS_S3_REGION=your_region -``` - -### 2. Changing Default Parsing Model - -By default, uploaded PDF files are parsed using `gpt-4o`. You can customize this by setting the following: - -```bash -# Override the default parsing model -export FILE_PARSING_MODEL=your-preferred-model -``` - -You can also change the model provider like so: -```bash -# Optional: Override the parsing provider settings -export FILE_PARSING_PROVIDER_BASE_URL=your-provider-base-url -export FILE_PARSING_PROVIDER_API_KEY=your-provider-api-key -``` - -### 3. Embedding Model Options - -By default, Rowboat uses OpenAI's `text-embedding-3-small` model for generating embeddings. You can customize this by setting the following: - -```bash -# Override the default embedding model -export EMBEDDING_MODEL=your-preferred-model -export EMBEDDING_VECTOR_SIZE=1536 -``` - -**Important NOTE** - -The default size for the vectors index is 1536. If you change this value, then you must delete the index and set it up again: -```bash -docker-compose --profile delete_qdrant --profile qdrant up --build delete_qdrant qdrant -``` -followed by: -```bash -./start # this will recreate the index -``` - -You can also change the model provider like so: -```bash -# Optional: Override the embedding provider settings -export EMBEDDING_PROVIDER_BASE_URL=your-provider-base-url -export EMBEDDING_PROVIDER_API_KEY=your-provider-api-key -``` - -If you don't specify the provider settings, Rowboat will use OpenAI as the default provider. diff --git a/apps/docs/docs/using_the_sdk.md b/apps/docs/docs/using_the_sdk.md deleted file mode 100644 index c867bcbc9..000000000 --- a/apps/docs/docs/using_the_sdk.md +++ /dev/null @@ -1,99 +0,0 @@ -# Using the Python SDK - -This is a guide on using the RowBoat Python SDK as an alternative to the [RowBoat HTTP API](/using_the_api) to power conversations with the assistant created in Studio. - -## Prerequisites -- ``` pip install rowboat ``` -- [Deploy your assistant to production](/using_the_api/#deploy-your-assistant-to-production-on-studio) -- [Obtain your `` and ``](/using_the_api/#obtain-api-key-and-project-id) - -### API Host -- For the open source installation, the `` is [http://localhost:3000](http://localhost:3000) -- When using the hosted app, the `` is [https://app.rowboatlabs.com](https://app.rowboatlabs.com) - -## Usage - -### Basic Usage with StatefulChat - -The easiest way to interact with Rowboat is using the `StatefulChat` class, which maintains conversation state automatically: - -```python -from rowboat import Client, StatefulChat - -# Initialize the client -client = Client( - host="", - project_id="", - api_key="" -) - -# Create a stateful chat session -chat = StatefulChat(client) - -# Have a conversation -response = chat.run("What is the capital of France?") -print(response) -# The capital of France is Paris. - -# Continue the conversation - the context is maintained automatically -response = chat.run("What other major cities are in that country?") -print(response) -# Other major cities in France include Lyon, Marseille, Toulouse, and Nice. - -response = chat.run("What's the population of the first city you mentioned?") -print(response) -# Lyon has a population of approximately 513,000 in the city proper. -``` - -### Advanced Usage - -#### Using a specific workflow - -You can specify a workflow ID to use a particular conversation configuration: - -```python -chat = StatefulChat( - client, - workflow_id="" -) -``` - -#### Using a test profile - -You can specify a test profile ID to use a specific test configuration: - -```python -chat = StatefulChat( - client, - test_profile_id="" -) -``` - -### Low-Level Usage - -For more control over the conversation, you can use the `Client` class directly: - -```python -from rowboat.schema import UserMessage - -# Initialize the client -client = Client( - host="", - project_id="", - api_key="" -) - -# Create messages -messages = [ - UserMessage(role='user', content="Hello, how are you?") -] - -# Get response -response = client.chat(messages=messages) -print(response.messages[-1].content) - -# For subsequent messages, you need to manage the message history and state manually -messages.extend(response.messages) -messages.append(UserMessage(role='user', content="What's your name?")) -response = client.chat(messages=messages, state=response.state) -``` \ No newline at end of file diff --git a/apps/docs/docs/videos/Intro-Video.gif b/apps/docs/docs/videos/Intro-Video.gif new file mode 100644 index 000000000..d4eb387ef Binary files /dev/null and b/apps/docs/docs/videos/Intro-Video.gif differ diff --git a/apps/docs/docs/videos/intro.mp4 b/apps/docs/docs/videos/intro.mp4 new file mode 100644 index 000000000..4306a886e Binary files /dev/null and b/apps/docs/docs/videos/intro.mp4 differ diff --git a/apps/docs/docs/img/favicon.ico b/apps/docs/favicon.ico similarity index 100% rename from apps/docs/docs/img/favicon.ico rename to apps/docs/favicon.ico diff --git a/apps/docs/mkdocs.yml b/apps/docs/mkdocs.yml deleted file mode 100644 index 4e5eb44c5..000000000 --- a/apps/docs/mkdocs.yml +++ /dev/null @@ -1,26 +0,0 @@ -site_name: RowBoat docs -site_url: https://docs.rowboatlabs.com -theme: - name: material - favicon: img/favicon.ico -nav: - - Getting Started: setup.md - - Overview: - - Introduction: index.md - - Open Source License: license.md - - - Building in Studio: - - Create agents: create_agents.md - - Test chats in the playground: playground.md - - Add tools: add_tools.md - - Update agents: update_agents.md - - Using RAG: using_rag.md - - - API & SDK: - - Using the API: using_the_api.md - - Using the SDK: using_the_sdk.md - - - Concepts: - - Agents: agents.md - - Tools: tools.md - - Prompts: prompts.md diff --git a/apps/docs/readme.md b/apps/docs/readme.md deleted file mode 100644 index 2783c5186..000000000 --- a/apps/docs/readme.md +++ /dev/null @@ -1,55 +0,0 @@ -# Documentation Site - -This documentation site is built using [MkDocs Material](https://squidfunk.github.io/mkdocs-material/), a modern documentation framework that creates beautiful and functional static sites. - -## Prerequisites - -- Python 3.x -- pip (Python package manager) - -## Setup - -Install the required dependencies: - -```bash -pip install -r requirements.txt -``` - -## Development - -To run the documentation site locally: - -```bash -mkdocs serve -``` - -This will start a local server, and you can view the documentation site at `http://localhost:8000`. - -### Building the static site - -To build the static site: - -```bash -mkdocs build -``` - -This will generate the static site in the `site` directory. - -### Project structure - -- `mkdocs.yml`: The main configuration file for MkDocs. -- `docs/`: The directory containing the Markdown files for the documentation. -- `site/`: The directory generated by the `mkdocs build` command, containing the static site files. - -## Writing Documentation - -- Documentation files are written in Markdown format -- Place new documentation files in the `docs` directory -- Update `mkdocs.yml` to include new pages in the navigation - -## Additional Resources - -- [Mkdocs documentation](https://www.mkdocs.org/getting-started/) -- [MkDocs Material Documentation](https://squidfunk.github.io/mkdocs-material/getting-started/) -- [Markdown Guide](https://www.markdownguide.org/basic-syntax/) - diff --git a/apps/docs/requirements.txt b/apps/docs/requirements.txt deleted file mode 100644 index fa6a6dd1d..000000000 --- a/apps/docs/requirements.txt +++ /dev/null @@ -1,29 +0,0 @@ -babel==2.16.0 -certifi==2024.12.14 -charset-normalizer==3.4.1 -click==8.1.8 -colorama==0.4.6 -ghp-import==2.1.0 -idna==3.10 -Jinja2==3.1.5 -Markdown==3.7 -MarkupSafe==3.0.2 -mergedeep==1.3.4 -mkdocs==1.6.1 -mkdocs-get-deps==0.2.0 -mkdocs-material==9.5.50 -mkdocs-material-extensions==1.3.1 -packaging==24.2 -paginate==0.5.7 -pathspec==0.12.1 -platformdirs==4.3.6 -Pygments==2.19.1 -pymdown-extensions==10.14.1 -python-dateutil==2.9.0.post0 -PyYAML==6.0.2 -pyyaml_env_tag==0.1 -regex==2024.11.6 -requests==2.32.3 -six==1.17.0 -urllib3==2.3.0 -watchdog==6.0.0 diff --git a/apps/experimental/simulation_runner/simulation.py b/apps/experimental/simulation_runner/simulation.py index 39618897d..f0a0c4d6a 100644 --- a/apps/experimental/simulation_runner/simulation.py +++ b/apps/experimental/simulation_runner/simulation.py @@ -11,7 +11,7 @@ from rowboat import Client, StatefulChat openai_client = OpenAI() -MODEL_NAME = "gpt-4o" +MODEL_NAME = "gpt-4.1" ROWBOAT_API_HOST = os.environ.get("ROWBOAT_API_HOST", "http://127.0.0.1:3000").strip() async def simulate_simulation( diff --git a/apps/rowboat/app/actions/assistant-templates.actions.ts b/apps/rowboat/app/actions/assistant-templates.actions.ts new file mode 100644 index 000000000..a525914d5 --- /dev/null +++ b/apps/rowboat/app/actions/assistant-templates.actions.ts @@ -0,0 +1,264 @@ +"use server"; + +import { z } from 'zod'; +import { authCheck } from "./auth.actions"; +import { MongoDBAssistantTemplatesRepository } from '@/src/infrastructure/repositories/mongodb.assistant-templates.repository'; +import { prebuiltTemplates } from '@/app/lib/prebuilt-cards'; +import { USE_AUTH } from '@/app/lib/feature_flags'; +// import { ensureLibraryTemplatesSeeded } from '@/app/lib/assistant_templates_seed'; + +const repo = new MongoDBAssistantTemplatesRepository(); + +// Helper function to serialize MongoDB objects for client components +function serializeTemplate(template: any) { + return JSON.parse(JSON.stringify(template)); +} + +function serializeTemplates(templates: any[]) { + return templates.map(serializeTemplate); +} + +const ListTemplatesSchema = z.object({ + category: z.string().optional(), + search: z.string().optional(), + featured: z.boolean().optional(), + source: z.enum(['library','community']).optional(), + cursor: z.string().optional(), + limit: z.number().min(1).max(50).default(20), +}); + +const CreateTemplateSchema = z.object({ + name: z.string().min(1).max(100), + description: z.string().min(1).max(500), + category: z.string().min(1), + tags: z.array(z.string()).max(10), + isAnonymous: z.boolean().default(false), + workflow: z.any(), + copilotPrompt: z.string().optional(), + thumbnailUrl: z.string().url().optional(), +}); + +type ListResponse = { items: any[]; nextCursor: string | null }; + +function buildPrebuiltList(params: z.infer): ListResponse { + const allPrebuilt = Object.entries(prebuiltTemplates).map(([key, tpl]) => ({ + id: `prebuilt:${key}`, + name: (tpl as any).name || key, + description: (tpl as any).description || '', + category: (tpl as any).category || 'Other', + tools: (tpl as any).tools || [], + createdAt: (tpl as any).lastUpdatedAt || undefined, + source: 'library' as const, + })); + + let filtered = allPrebuilt; + if (params.category) { + filtered = filtered.filter(t => t.category === params.category); + } + if (params.search) { + const q = params.search.toLowerCase(); + filtered = filtered.filter(t => + t.name.toLowerCase().includes(q) || + t.description.toLowerCase().includes(q) || + t.category.toLowerCase().includes(q) + ); + } + + const startIndex = params.cursor ? parseInt(params.cursor, 10) || 0 : 0; + const endIndex = Math.min(startIndex + params.limit, filtered.length); + const pageItems = filtered.slice(startIndex, endIndex); + const nextCursor = endIndex < filtered.length ? String(endIndex) : null; + + return { items: pageItems, nextCursor }; +} + +export async function listAssistantTemplates(request: z.infer): Promise { + const user = await authCheck(); + + // Prebuilt templates should never be seeded to DB + + const params = ListTemplatesSchema.parse(request); + + // If source specified, return that subset; for 'library' use in-memory prebuilt from code + if (params.source === 'library') { + const { items, nextCursor } = buildPrebuiltList(params); + return { items: serializeTemplates(items), nextCursor }; + } + + if (params.source === 'community') { + const result = await repo.list({ + category: params.category, + search: params.search, + featured: params.featured, + isPublic: true, + source: 'community', + }, params.cursor, params.limit); + + const itemsWithLikeStatus = await addLikeStatusToTemplates(result.items, user.id); + return { ...result, items: serializeTemplates(itemsWithLikeStatus) }; + } + + // No source: return prebuilt from code + first page of community from DB + const prebuilt = buildPrebuiltList({ ...params, source: 'library' } as any).items; + const communityPage = await repo.list({ + category: params.category, + search: params.search, + featured: params.featured, + isPublic: true, + source: 'community', + }, undefined, params.limit); + const items = [...prebuilt, ...communityPage.items]; + return { items: serializeTemplates(items), nextCursor: null }; +} + +// Get a specific template by ID with model transformation +export async function getAssistantTemplate(templateId: string) { + const user = await authCheck(); + + // Prebuilt: load directly from code + if (templateId.startsWith('prebuilt:')) { + const key = templateId.replace('prebuilt:', ''); + const originalTemplate = prebuiltTemplates[key as keyof typeof prebuiltTemplates]; + if (!originalTemplate) throw new Error('Template not found'); + + const defaultModel = process.env.PROVIDER_DEFAULT_MODEL || 'gpt-4.1'; + const transformedWorkflow = JSON.parse(JSON.stringify(originalTemplate)); + if (transformedWorkflow.agents && Array.isArray(transformedWorkflow.agents)) { + transformedWorkflow.agents.forEach((agent: any) => { + if (agent.model === '') { + agent.model = defaultModel; + } + }); + } + + // Return minimal shape expected by callers + const result = { + id: templateId, + name: (originalTemplate as any).name || key, + description: (originalTemplate as any).description || '', + category: (originalTemplate as any).category || 'Other', + workflow: transformedWorkflow, + source: 'library' as const, + }; + return serializeTemplate(result); + } + + // Community template from DB + const template = await repo.fetch(templateId); + if (!template) throw new Error('Template not found'); + return serializeTemplate(template); +} + +export async function getAssistantTemplateCategories() { + const user = await authCheck(); + + const categories = await repo.getCategories(); + return { items: categories }; +} + + +export async function createAssistantTemplate(data: z.infer) { + const user = await authCheck(); + + const validatedData = CreateTemplateSchema.parse(data); + + let authorName = 'Anonymous'; + let authorEmail: string | undefined; + + if (USE_AUTH) { + try { + const { auth0 } = await import('@/app/lib/auth0'); + const { user: auth0User } = await auth0.getSession() || {}; + if (auth0User) { + authorName = auth0User.name ?? auth0User.email ?? 'Anonymous'; + authorEmail = auth0User.email; + } + } catch (error) { + console.warn('Could not get Auth0 user info:', error); + } + } + + if (validatedData.isAnonymous) { + authorName = 'Anonymous'; + authorEmail = undefined; + } + + const created = await repo.create({ + name: validatedData.name, + description: validatedData.description, + category: validatedData.category, + authorId: user.id, + authorName, + authorEmail, + isAnonymous: validatedData.isAnonymous, + workflow: validatedData.workflow, + tags: validatedData.tags, + copilotPrompt: validatedData.copilotPrompt, + thumbnailUrl: validatedData.thumbnailUrl, + downloadCount: 0, + likeCount: 0, + featured: false, + isPublic: true, + likes: [], + source: 'community', + }); + + return serializeTemplate(created); +} + +export async function deleteAssistantTemplate(id: string) { + const user = await authCheck(); + + const item = await repo.fetch(id); + if (!item) { + throw new Error('Template not found'); + } + + // Disallow deleting library/prebuilt items + if ((item as any).source === 'library' || item.authorId === 'rowboat-system') { + throw new Error('Not allowed to delete this template'); + } + + if (item.authorId !== user.id) { + // Do not reveal existence + throw new Error('Template not found'); + } + + const ok = await repo.deleteByIdAndAuthor(id, user.id); + if (!ok) { + throw new Error('Template not found'); + } + + return { success: true }; +} + +export async function toggleTemplateLike(id: string) { + const user = await authCheck(); + + // Use authenticated user ID instead of guest ID + const result = await repo.toggleLike(id, user.id); + return serializeTemplate(result); +} + +export async function getCurrentUser() { + const user = await authCheck(); + return { id: user.id }; +} + +// Helper function to add isLiked status to templates +async function addLikeStatusToTemplates(templates: any[], userId: string) { + if (templates.length === 0) return templates; + + // Get all template IDs + const templateIds = templates.map(t => t.id); + + // Check which templates the user has liked + const likedTemplates = await repo.getLikedTemplates(templateIds, userId); + const likedSet = new Set(likedTemplates); + + // Add isLiked property to each template + return templates.map(template => ({ + ...template, + isLiked: likedSet.has(template.id) + })); +} diff --git a/apps/rowboat/app/actions/composio.actions.ts b/apps/rowboat/app/actions/composio.actions.ts index daddc9308..8af20aaa6 100644 --- a/apps/rowboat/app/actions/composio.actions.ts +++ b/apps/rowboat/app/actions/composio.actions.ts @@ -157,6 +157,7 @@ export async function createComposioTriggerDeployment(request: { export async function listComposioTriggerDeployments(request: { projectId: string, cursor?: string, + limit?: number, }) { const user = await authCheck(); @@ -166,6 +167,7 @@ export async function listComposioTriggerDeployments(request: { userId: user.id, projectId: request.projectId, cursor: request.cursor, + limit: request.limit, }); } @@ -191,4 +193,4 @@ export async function fetchComposioTriggerDeployment(request: { deploymentId: st userId: user.id, deploymentId: request.deploymentId, }); -} \ No newline at end of file +} diff --git a/apps/rowboat/app/actions/copilot.actions.ts b/apps/rowboat/app/actions/copilot.actions.ts index de9b1baec..e4d867311 100644 --- a/apps/rowboat/app/actions/copilot.actions.ts +++ b/apps/rowboat/app/actions/copilot.actions.ts @@ -3,6 +3,7 @@ import { CopilotAPIRequest, CopilotChatContext, CopilotMessage, DataSourceSchemaForCopilot, + TriggerSchemaForCopilot, } from "../../src/entities/models/copilot"; import { Workflow} from "../lib/types/workflow_types"; @@ -26,7 +27,8 @@ export async function getCopilotResponseStream( messages: z.infer[], current_workflow_config: z.infer, context: z.infer | null, - dataSources?: z.infer[] + dataSources?: z.infer[], + triggers?: z.infer[] ): Promise<{ streamId: string; } | { billingError: string }> { @@ -42,6 +44,7 @@ export async function getCopilotResponseStream( workflow: current_workflow_config, context, dataSources, + triggers, } }); return { diff --git a/apps/rowboat/app/actions/project.actions.ts b/apps/rowboat/app/actions/project.actions.ts index 5f0426944..c8a0182ca 100644 --- a/apps/rowboat/app/actions/project.actions.ts +++ b/apps/rowboat/app/actions/project.actions.ts @@ -2,7 +2,8 @@ import { z } from 'zod'; import { container } from "@/di/container"; import { redirect } from "next/navigation"; -import { templates } from "../lib/project_templates"; +// Fetch library templates from the unified assistant templates repository +import { MongoDBAssistantTemplatesRepository } from "@/src/infrastructure/repositories/mongodb.assistant-templates.repository"; import { authCheck } from "./auth.actions"; import { ApiKey } from "@/src/entities/models/api-key"; import { Project } from "@/src/entities/models/project"; @@ -40,14 +41,17 @@ const updateLiveWorkflowController = container.resolve('revertToLiveWorkflowController'); export async function listTemplates() { - const templatesArray = Object.entries(templates) - .filter(([key]) => key !== 'default') // Exclude the default template - .map(([key, template]) => ({ - id: key, - ...template - })); - - return templatesArray; + const repo = new MongoDBAssistantTemplatesRepository(); + const result = await repo.list({ source: 'library', isPublic: true }, undefined, 100); + // Map to the shape expected by callers (tools at top-level) + return result.items.map((item) => ({ + id: item.id, + name: item.name, + description: item.description, + category: item.category, + tools: (item as any).workflow?.tools || [], + copilotPrompt: item.copilotPrompt, + })); } export async function projectAuthCheck(projectId: string) { @@ -93,12 +97,24 @@ export async function createProjectFromWorkflowJson(formData: FormData): Promise const workflowJson = formData.get('workflowJson') as string; try { + // Parse workflow and apply default model to blank agent models + const workflow = JSON.parse(workflowJson); + const defaultModel = process.env.PROVIDER_DEFAULT_MODEL || 'gpt-4o'; + + if (workflow.agents && Array.isArray(workflow.agents)) { + workflow.agents.forEach((agent: any) => { + if (agent.model === '') { + agent.model = defaultModel; + } + }); + } + const project = await createProjectController.execute({ userId: user.id, data: { name: name || '', mode: { - workflowJson, + workflowJson: JSON.stringify(workflow), }, }, }); diff --git a/apps/rowboat/app/actions/recurring-job-rules.actions.ts b/apps/rowboat/app/actions/recurring-job-rules.actions.ts index d64264d84..b807aa3b7 100644 --- a/apps/rowboat/app/actions/recurring-job-rules.actions.ts +++ b/apps/rowboat/app/actions/recurring-job-rules.actions.ts @@ -6,6 +6,7 @@ import { IListRecurringJobRulesController } from "@/src/interface-adapters/contr import { IFetchRecurringJobRuleController } from "@/src/interface-adapters/controllers/recurring-job-rules/fetch-recurring-job-rule.controller"; import { IToggleRecurringJobRuleController } from "@/src/interface-adapters/controllers/recurring-job-rules/toggle-recurring-job-rule.controller"; import { IDeleteRecurringJobRuleController } from "@/src/interface-adapters/controllers/recurring-job-rules/delete-recurring-job-rule.controller"; +import { IUpdateRecurringJobRuleController } from "@/src/interface-adapters/controllers/recurring-job-rules/update-recurring-job-rule.controller"; import { authCheck } from "./auth.actions"; import { z } from "zod"; import { Message } from "@/app/lib/types/types"; @@ -15,6 +16,7 @@ const listRecurringJobRulesController = container.resolve('fetchRecurringJobRuleController'); const toggleRecurringJobRuleController = container.resolve('toggleRecurringJobRuleController'); const deleteRecurringJobRuleController = container.resolve('deleteRecurringJobRuleController'); +const updateRecurringJobRuleController = container.resolve('updateRecurringJobRuleController'); export async function createRecurringJobRule(request: { projectId: string, @@ -89,3 +91,23 @@ export async function deleteRecurringJobRule(request: { ruleId: request.ruleId, }); } + +export async function updateRecurringJobRule(request: { + projectId: string, + ruleId: string, + input: { + messages: z.infer[], + }, + cron: string, +}) { + const user = await authCheck(); + + return await updateRecurringJobRuleController.execute({ + caller: 'user', + userId: user.id, + projectId: request.projectId, + ruleId: request.ruleId, + input: request.input, + cron: request.cron, + }); +} diff --git a/apps/rowboat/app/actions/scheduled-job-rules.actions.ts b/apps/rowboat/app/actions/scheduled-job-rules.actions.ts index 640c4e08f..144475a07 100644 --- a/apps/rowboat/app/actions/scheduled-job-rules.actions.ts +++ b/apps/rowboat/app/actions/scheduled-job-rules.actions.ts @@ -5,6 +5,7 @@ import { ICreateScheduledJobRuleController } from "@/src/interface-adapters/cont import { IListScheduledJobRulesController } from "@/src/interface-adapters/controllers/scheduled-job-rules/list-scheduled-job-rules.controller"; import { IFetchScheduledJobRuleController } from "@/src/interface-adapters/controllers/scheduled-job-rules/fetch-scheduled-job-rule.controller"; import { IDeleteScheduledJobRuleController } from "@/src/interface-adapters/controllers/scheduled-job-rules/delete-scheduled-job-rule.controller"; +import { IUpdateScheduledJobRuleController } from "@/src/interface-adapters/controllers/scheduled-job-rules/update-scheduled-job-rule.controller"; import { authCheck } from "./auth.actions"; import { z } from "zod"; import { Message } from "@/app/lib/types/types"; @@ -13,6 +14,7 @@ const createScheduledJobRuleController = container.resolve('listScheduledJobRulesController'); const fetchScheduledJobRuleController = container.resolve('fetchScheduledJobRuleController'); const deleteScheduledJobRuleController = container.resolve('deleteScheduledJobRuleController'); +const updateScheduledJobRuleController = container.resolve('updateScheduledJobRuleController'); export async function createScheduledJobRule(request: { projectId: string, @@ -72,4 +74,24 @@ export async function deleteScheduledJobRule(request: { projectId: request.projectId, ruleId: request.ruleId, }); -} \ No newline at end of file +} + +export async function updateScheduledJobRule(request: { + projectId: string, + ruleId: string, + input: { + messages: z.infer[], + }, + scheduledTime: string, +}) { + const user = await authCheck(); + + return await updateScheduledJobRuleController.execute({ + caller: 'user', + userId: user.id, + projectId: request.projectId, + ruleId: request.ruleId, + input: request.input, + scheduledTime: request.scheduledTime, + }); +} diff --git a/apps/rowboat/app/actions/shared-workflow.actions.ts b/apps/rowboat/app/actions/shared-workflow.actions.ts new file mode 100644 index 000000000..f651d4a55 --- /dev/null +++ b/apps/rowboat/app/actions/shared-workflow.actions.ts @@ -0,0 +1,65 @@ +"use server"; + +import { z } from "zod"; +import { nanoid } from "nanoid"; +import { Workflow } from "@/app/lib/types/workflow_types"; +import { db } from "@/app/lib/mongodb"; +import { SHARED_WORKFLOWS_COLLECTION } from "@/src/infrastructure/repositories/mongodb.shared-workflows.indexes"; +import { requireAuth } from "@/app/lib/auth"; + +const DEFAULT_TTL_SECONDS = 60 * 60 * 24; // 24 hours + +interface SharedWorkflowDoc { + _id: string; + workflow: unknown; + createdAt: Date; + expiresAt: Date; +} + +function validateWorkflowJson(obj: unknown) { + const parsed = Workflow.safeParse(obj); + if (!parsed.success) { + const message = parsed.error.issues.map(i => `${i.path.join('.')}: ${i.message}`).join('; '); + throw new Error(`Invalid workflow JSON: ${message}`); + } + return parsed.data; +} + +export async function createSharedWorkflowFromJson(json: string): Promise<{ id: string; ttlSeconds: number; }> +{ + // Require an authenticated user (respects guest mode when auth is disabled) + await requireAuth(); + const obj = JSON.parse(json); + const workflow = validateWorkflowJson(obj); + + const coll = db.collection(SHARED_WORKFLOWS_COLLECTION); + const id = nanoid(); + const now = new Date(); + const expiresAt = new Date(now.getTime() + DEFAULT_TTL_SECONDS * 1000); + await coll.insertOne({ _id: id, workflow, createdAt: now, expiresAt }); + + return { id, ttlSeconds: DEFAULT_TTL_SECONDS }; +} + +/** + * Load a shared workflow by ephemeral share id stored in MongoDB. + * Expected when the query param `shared` is present in the UI. + */ +export async function loadSharedWorkflow(id: string): Promise> { + // Ensure caller is authenticated (guest allowed when auth disabled) + await requireAuth(); + + // Look up by shared id in MongoDB + const coll = db.collection(SHARED_WORKFLOWS_COLLECTION); + const doc = await coll.findOne( + { _id: id }, + { projection: { workflow: 1, expiresAt: 1 } } + ); + if (!doc) { + throw new Error('Not found or expired'); + } + if (doc.expiresAt && doc.expiresAt.getTime() <= Date.now()) { + throw new Error('Not found or expired'); + } + return validateWorkflowJson(doc.workflow); +} diff --git a/apps/rowboat/app/api/generated-images/[id]/route.ts b/apps/rowboat/app/api/generated-images/[id]/route.ts new file mode 100644 index 000000000..e93124980 --- /dev/null +++ b/apps/rowboat/app/api/generated-images/[id]/route.ts @@ -0,0 +1,74 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { S3Client, GetObjectCommand, HeadObjectCommand } from '@aws-sdk/client-s3'; +import { Readable } from 'stream'; + +// Serves generated images from S3 by UUID-only path: /api/generated-images/{id} +// Reconstructs the S3 key using the same sharding logic as image creation. +export async function GET(request: NextRequest, props: { params: Promise<{ id: string }> }) { + const params = await props.params; + const id = params.id; + if (!id) { + return NextResponse.json({ error: 'Missing id' }, { status: 400 }); + } + + const bucket = process.env.RAG_UPLOADS_S3_BUCKET || ''; + if (!bucket) { + return NextResponse.json({ error: 'S3 bucket not configured' }, { status: 500 }); + } + + const region = process.env.RAG_UPLOADS_S3_REGION || 'us-east-1'; + const s3 = new S3Client({ + region, + credentials: process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY ? { + accessKeyId: process.env.AWS_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, + } as any : undefined, + }); + + // Reconstruct directory sharding from last two characters of UUID + const last2 = id.slice(-2).padStart(2, '0'); + const dirA = last2.charAt(0); + const dirB = last2.charAt(1); + const baseKey = `generated_images/${dirA}/${dirB}/${id}`; + + // Try known extensions in order used by generator + const exts = ['.png', '.jpg', '.webp']; + let foundExt: string | null = null; + for (const ext of exts) { + try { + await s3.send(new HeadObjectCommand({ Bucket: bucket, Key: `${baseKey}${ext}` })); + foundExt = ext; + break; + } catch { + // continue trying next extension + } + } + + if (!foundExt) { + return NextResponse.json({ error: 'Not found' }, { status: 404 }); + } + + const key = `${baseKey}${foundExt}`; + const filename = `${id}${foundExt}`; + try { + const resp = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key })); + const contentType = resp.ContentType || 'application/octet-stream'; + const body = resp.Body as any; + const webStream = body?.transformToWebStream + ? body.transformToWebStream() + : (Readable as any)?.toWeb + ? (Readable as any).toWeb(body) + : body; + return new NextResponse(webStream, { + status: 200, + headers: { + 'Content-Type': contentType, + 'Cache-Control': 'public, max-age=31536000, immutable', + 'Content-Disposition': `inline; filename="${filename}"`, + }, + }); + } catch (e) { + console.error('S3 get error', e); + return NextResponse.json({ error: 'Not found' }, { status: 404 }); + } +} diff --git a/apps/rowboat/app/api/me/route.ts b/apps/rowboat/app/api/me/route.ts new file mode 100644 index 000000000..b1591439b --- /dev/null +++ b/apps/rowboat/app/api/me/route.ts @@ -0,0 +1,19 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { authCheck } from '@/app/actions/auth.actions'; +import { USE_AUTH } from '@/app/lib/feature_flags'; + +export async function GET(_req: NextRequest) { + try { + let user; + if (USE_AUTH) { + user = await authCheck(); + } else { + user = { id: 'guest_user' } as any; + } + return NextResponse.json({ id: user.id }); + } catch (error) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); + } +} + + diff --git a/apps/rowboat/app/api/templates/route.ts b/apps/rowboat/app/api/templates/route.ts deleted file mode 100644 index 4a7cd74eb..000000000 --- a/apps/rowboat/app/api/templates/route.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { NextResponse } from 'next/server'; -import { templates } from '@/app/lib/project_templates'; - -export async function GET() { - return NextResponse.json(templates); -} diff --git a/apps/rowboat/app/api/tmp-images/[id]/route.ts b/apps/rowboat/app/api/tmp-images/[id]/route.ts new file mode 100644 index 000000000..cf7bfb644 --- /dev/null +++ b/apps/rowboat/app/api/tmp-images/[id]/route.ts @@ -0,0 +1,25 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { tempBinaryCache } from '@/src/application/services/temp-binary-cache'; + +export async function GET(request: NextRequest, props: { params: Promise<{ id: string }> }) { + const params = await props.params; + const id = params.id; + if (!id) { + return NextResponse.json({ error: 'Missing id' }, { status: 400 }); + } + + // Serve from in-memory temp cache + const entry = tempBinaryCache.get(id); + if (!entry) { + return NextResponse.json({ error: 'Not found or expired' }, { status: 404 }); + } + + return new NextResponse(entry.buf, { + status: 200, + headers: { + 'Content-Type': entry.mimeType || 'application/octet-stream', + 'Cache-Control': 'no-store', + 'Content-Disposition': `inline; filename="${id}"`, + }, + }); +} diff --git a/apps/rowboat/app/components/ui/textarea-with-send.tsx b/apps/rowboat/app/components/ui/textarea-with-send.tsx index 965315549..0c57c3c4c 100644 --- a/apps/rowboat/app/components/ui/textarea-with-send.tsx +++ b/apps/rowboat/app/components/ui/textarea-with-send.tsx @@ -2,7 +2,8 @@ import { forwardRef, TextareaHTMLAttributes } from 'react'; import { Textarea } from '@/components/ui/textarea'; -import { Send } from 'lucide-react'; +import { Send, Plus } from 'lucide-react'; +import { Dropdown, DropdownItem, DropdownMenu, DropdownTrigger } from '@heroui/react'; import clsx from 'clsx'; interface TextareaWithSendProps extends Omit, 'onChange'> { @@ -11,6 +12,9 @@ interface TextareaWithSendProps extends Omit void; isSubmitting?: boolean; submitDisabled?: boolean; + onImportJson?: () => void; + importDisabled?: boolean; + isImporting?: boolean; placeholder?: string; className?: string; rows?: number; @@ -25,6 +29,9 @@ export const TextareaWithSend = forwardRef { + const hasMore = Boolean(onImportJson); return (