Skip to content

Commit 448f94a

Browse files
authored
Merge pull request #227 from rowboatlabs/dev
Dev
2 parents 2368d1b + 49e6711 commit 448f94a

File tree

17 files changed

+327
-345
lines changed

17 files changed

+327
-345
lines changed

apps/docs/docs.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
"socials": {
6969
"github": "https://github.com/rowboatlabs/rowboat",
7070
"linkedin": "https://www.linkedin.com/company/rowboat-labs",
71-
"discord": "https://discord.gg/PCkH9TWC"
71+
"discord": "https://discord.gg/rxB8pzHxaS"
7272
}
7373
},
7474
"contextual": {

apps/docs/docs/api-sdk/using_the_sdk.mdx

Lines changed: 47 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -15,87 +15,77 @@ icon: "toolbox"
1515

1616
## Usage
1717

18-
### Basic Usage with StatefulChat
18+
### Basic Usage
1919

20-
The easiest way to interact with Rowboat is using the `StatefulChat` class, which maintains conversation state automatically:
20+
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.
2121

2222
```python
23-
from rowboat import Client, StatefulChat
23+
from rowboat.client import Client
24+
from rowboat.schema import UserMessage
2425

2526
# Initialize the client
2627
client = Client(
2728
host="<HOST>",
28-
project_id="<PROJECT_ID>",
29-
api_key="<API_KEY>"
29+
projectId="<PROJECT_ID>",
30+
apiKey="<API_KEY>"
3031
)
3132

32-
# Create a stateful chat session
33-
chat = StatefulChat(client)
34-
35-
# Have a conversation
36-
response = chat.run("What is the capital of France?")
37-
print(response)
33+
# Start a new conversation
34+
result = client.run_turn(
35+
messages=[
36+
UserMessage(role='user', content="What is the capital of France?")
37+
]
38+
)
39+
print(result.turn.output[-1].content)
3840
# The capital of France is Paris.
3941

40-
# Continue the conversation - the context is maintained automatically
41-
response = chat.run("What other major cities are in that country?")
42-
print(response)
43-
# Other major cities in France include Lyon, Marseille, Toulouse, and Nice.
42+
print("Conversation ID:", result.conversationId)
4443

45-
response = chat.run("What's the population of the first city you mentioned?")
46-
print(response)
47-
# Lyon has a population of approximately 513,000 in the city proper.
48-
```
49-
50-
### Advanced Usage
51-
52-
#### Using a specific workflow
53-
54-
You can specify a workflow ID to use a particular conversation configuration:
44+
# Continue the conversation by passing the conversationId
45+
result = client.run_turn(
46+
messages=[
47+
UserMessage(role='user', content="What other major cities are in that country?")
48+
],
49+
conversationId=result.conversationId
50+
)
51+
print(result.turn.output[-1].content)
52+
# Other major cities in France include Lyon, Marseille, Toulouse, and Nice.
5553

56-
```python
57-
chat = StatefulChat(
58-
client,
59-
workflow_id="<WORKFLOW_ID>"
54+
result = client.run_turn(
55+
messages=[
56+
UserMessage(role='user', content="What's the population of the first city you mentioned?")
57+
],
58+
conversationId=result.conversationId
6059
)
60+
print(result.turn.output[-1].content)
61+
# Lyon has a population of approximately 513,000 in the city proper.
6162
```
6263

63-
#### Using a test profile
64+
### Using Tool Overrides (Mock Tools)
6465

65-
You can specify a test profile ID to use a specific test configuration:
66+
You can provide tool override instructions to test a specific configuration using the `mockTools` argument:
6667

6768
```python
68-
chat = StatefulChat(
69-
client,
70-
test_profile_id="<TEST_PROFILE_ID>"
69+
result = client.run_turn(
70+
messages=[
71+
UserMessage(role='user', content="What's the weather?")
72+
],
73+
mockTools={
74+
"weather_lookup": "The weather in any city is sunny and 25°C.",
75+
"calculator": "The result of any calculation is 42."
76+
}
7177
)
78+
print(result.turn.output[-1].content)
7279
```
7380

74-
### Low-Level Usage
75-
76-
For more control over the conversation, you can use the `Client` class directly:
81+
### Message Types
7782

78-
```python
79-
from rowboat.schema import UserMessage
83+
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.
8084

81-
# Initialize the client
82-
client = Client(
83-
host="<HOST>",
84-
project_id="<PROJECT_ID>",
85-
api_key="<API_KEY>"
86-
)
85+
### Error Handling
8786

88-
# Create messages
89-
messages = [
90-
UserMessage(role='user', content="Hello, how are you?")
91-
]
87+
If the API returns a non-200 status code, a `ValueError` will be raised with the error details.
9288

93-
# Get response
94-
response = client.chat(messages=messages)
95-
print(response.messages[-1].content)
89+
---
9690

97-
# For subsequent messages, you need to manage the message history and state manually
98-
messages.extend(response.messages)
99-
messages.append(UserMessage(role='user', content="What's your name?"))
100-
response = client.chat(messages=messages, state=response.state)
101-
```
91+
For more advanced usage, see the docstrings in `client.py` and the message schemas in `schema.py`.

apps/docs/docs/development/contribution-guide.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ We're building Rowboat as an open-source, community-powered platform — and we'
2121
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.
2222

2323
- **Join the Community**
24-
Our [Discord](https://discord.gg/PCkH9TWC) is the go-to hub for brainstorming, feedback, and finding contributors for bigger efforts.
24+
Our [Discord](https://discord.gg/rxB8pzHxaS) is the go-to hub for brainstorming, feedback, and finding contributors for bigger efforts.
2525

2626
- **Propose Something New**
2727
Have a new tool integration idea or found a bug? Open an issue and let’s discuss it!

apps/docs/docs/getting-started/introduction.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: "Introduction"
3-
description: "Welcome to the official Rowboat documentation! 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."
3+
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."
44
icon: "book-open"
55
---
66

@@ -11,9 +11,9 @@ icon: "book-open"
1111
## What is RowBoat?
1212
**RowBoat is a state-of-art platform to build multi-agent AI systems in a visual interface, with the help of a copilot.**
1313

14-
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.
14+
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.
1515

16-
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.
16+
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.
1717

1818
---
1919

@@ -34,12 +34,12 @@ There are key components that you will work with:
3434

3535
### RowBoat Chat API & SDK
3636
- [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.
37-
- [RowBoat Chat SDK](/docs/api-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.
37+
- [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.
3838

3939
---
4040

4141
## Why RowBoat?
42-
Rowboat is the fastest way to build and deploy MCP connected multi-agents
42+
Rowboat is the fastest way to build and deploy multi-agent assistants.
4343

4444
<Steps>
4545
<Step title="Build complex assistants">

apps/docs/docs/getting-started/quickstart.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Using the open-source version of Rowboat requires more technical skill to set up
4141
```bash
4242
git clone git@github.com:rowboatlabs/rowboat.git
4343
cd rowboat
44-
docker-compose up --build
44+
./start.sh
4545
```
4646
</Step>
4747

apps/docs/docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Rowboat is a low-code AI IDE to build MCP tools connected multi-agent assistants
55
**Note:** These docs are intended for developers who would like to use our [open-source code](https://github.com/rowboatlabs/rowboat/).
66

77
- Our source code is on GitHub at [@rowboatlabs/rowboat](https://github.com/rowboatlabs/rowboat/)
8-
- Join us on [discord](https://discord.gg/jHhUKkKHn8)
8+
- Join us on [discord](https://discord.gg/rxB8pzHxaS)
99
- Email us at [founders@rowboatlabs.com](mailto:founders@rowboatlabs.com)
1010
- Visit our [website](https://www.rowboatlabs.com/)
1111

apps/docs/docs/using-rowboat/tools.mdx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,17 @@ The Tools page in Rowboat lets you add and configure tools that your agents can
2626
- Browse a library of 500+ toolkits from popular services
2727
- With 3000+ tools to choose from!
2828
- Click on a service to see available tools and add them to your workflow
29-
- Users must create a Composio account and add their API key
29+
- Users must create a [Composio](https://composio.dev/) account and add their API key
3030
- Tools require authorization to work properly
3131

32+
### Setting up Composio API Key
33+
34+
To use Composio tools, get a Composio key and export it as an environment variable:
35+
36+
```bash
37+
export COMPOSIO_API_KEY=your_api_key_here
38+
```
39+
3240
<Note>Users can visit [Composio's toolkit documentation](https://docs.composio.dev/toolkits/introduction) for a deep dive into all the tools available.</Note>
3341

3442
## Custom MCP Servers

apps/rowboat/app/lib/feature_flags.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,3 @@ export const SHOW_COPILOT_MARQUEE = false;
1818
export const SHOW_PROMPTS_SECTION = true;
1919
export const SHOW_DARK_MODE_TOGGLE = false;
2020
export const SHOW_VISUALIZATION = false;
21-
export const SHOW_PREBUILT_CARDS = false;

apps/rowboat/app/projects/[projectId]/copilot/app.tsx

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -265,18 +265,10 @@ const App = forwardRef<{ handleCopyChat: () => void; handleUserMessage: (message
265265
workflow={workflowRef.current}
266266
dispatch={dispatch}
267267
onStatusBarChange={handleStatusBarChange}
268+
toolCalling={toolCalling}
269+
toolQuery={toolQuery}
268270
/>
269271
</div>
270-
{toolCalling && (
271-
<div className="shrink-0 px-4 py-2.5 bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 shadow-sm dark:shadow-gray-950/20 rounded-2xl mx-1 mb-2">
272-
<div className="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400">
273-
<Spinner size="sm" className="ml-2" />
274-
<span>
275-
Searching for tools{toolQuery ? ` to ${toolQuery}` : '...'}
276-
</span>
277-
</div>
278-
</div>
279-
)}
280272
<div className="shrink-0 px-1">
281273
{responseError && (
282274
<div className="mb-4 p-2 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg flex gap-2 justify-between items-center text-sm">

apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
'use client';
2-
import { createContext, useContext, useRef, useState } from "react";
2+
import { createContext, useContext, useRef, useState, useEffect } from "react";
33
import clsx from "clsx";
44
import { z } from "zod";
55
import { CopilotAssistantMessageActionPart } from "../../../../../src/entities/models/copilot";
@@ -8,6 +8,7 @@ import { PreviewModalProvider, usePreviewModal } from '../../workflow/preview-mo
88
import { getAppliedChangeKey } from "../app";
99
import { AlertTriangleIcon, CheckCheckIcon, CheckIcon, ChevronsDownIcon, ChevronsUpIcon, EyeIcon, PencilIcon, PlusIcon } from "lucide-react";
1010
import { Spinner } from "@heroui/react";
11+
import { PictureImg } from "@/components/ui/picture-img";
1112

1213
const ActionContext = createContext<{
1314
msgIndex: number;
@@ -158,6 +159,33 @@ export function Action({
158159
);
159160
}
160161

162+
// Determine composio toolkit logo for tools
163+
const toolkitLogo = (() => {
164+
if (action.config_type !== 'tool') return undefined;
165+
const getLogo = (o: any): string | undefined => {
166+
return (
167+
o?.composioData?.logo ||
168+
o?.composioData?.logoUrl ||
169+
o?.composio?.logo ||
170+
o?.toolkit?.logo ||
171+
o?.composio_tool?.toolkit?.logo ||
172+
o?.logo ||
173+
undefined
174+
);
175+
};
176+
// Try various shapes the action might use
177+
const a: any = action as any;
178+
return (
179+
getLogo(a.config_changes) ||
180+
getLogo(a) ||
181+
getLogo(a.config_changes?.tool) ||
182+
getLogo(a.config_changes?.composio_tool) ||
183+
getLogo(a.tool) ||
184+
(workflow.tools.find(t => t.name === action.name) as any)?.composioData?.logo ||
185+
undefined
186+
);
187+
})();
188+
161189
return <div className={clsx(
162190
'flex flex-col rounded-md border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 shadow-xs',
163191
'transition-shadow duration-150',
@@ -170,17 +198,21 @@ export function Action({
170198
)}>
171199
<ActionContext.Provider value={{ msgIndex, actionIndex, action, workflow, appliedFields, stale }}>
172200
<div className="flex items-center gap-2 px-2 py-1 border-b border-zinc-100 dark:border-zinc-800">
173-
{/* Small colored icon for type */}
201+
{/* Small colored icon for type; show composio toolkit logo for tools when available */}
174202
<span className={clsx(
175-
'inline-flex items-center justify-center rounded-full h-5 w-5 text-xs',
203+
'inline-flex items-center justify-center rounded-full h-5 w-5 text-xs overflow-hidden',
176204
{
177205
'bg-blue-100 text-blue-600': action.action == 'create_new',
178206
'bg-yellow-100 text-yellow-600': action.action == 'edit',
179207
'bg-red-100 text-red-600': action.action == 'delete',
180208
'bg-gray-200 text-gray-600': stale || allApplied || action.error,
181209
}
182210
)}>
183-
{action.config_type === 'agent' ? '🧑‍💼' : action.config_type === 'tool' ? '🛠️' : action.config_type === 'pipeline' ? '⚙️' : action.config_type === 'start_agent' ? '🏁' : action.config_type === 'prompt' ? '💬' : '💬'}
211+
{action.config_type === 'tool' && toolkitLogo ? (
212+
<PictureImg src={toolkitLogo} alt={"Toolkit logo"} className="h-5 w-5 object-contain" />
213+
) : (
214+
action.config_type === 'agent' ? '🧑‍💼' : action.config_type === 'tool' ? '🛠️' : action.config_type === 'pipeline' ? '⚙️' : action.config_type === 'start_agent' ? '🏁' : action.config_type === 'prompt' ? '💬' : '💬'
215+
)}
184216
</span>
185217
<span className="font-semibold text-sm text-zinc-800 dark:text-zinc-100 truncate flex-1">
186218
{action.action === 'create_new' ? 'Add' : action.action === 'edit' ? 'Edit' : 'Delete'} {action.config_type}: {action.name}
@@ -352,6 +384,17 @@ export function StreamingAction({
352384
};
353385
loading: boolean;
354386
}) {
387+
const [loadingStage, setLoadingStage] = useState<'fetching' | 'configuring'>('fetching');
388+
389+
// After 3 seconds, switch to "configuring" stage
390+
useEffect(() => {
391+
const timer = setTimeout(() => {
392+
setLoadingStage('configuring');
393+
}, 3000);
394+
395+
return () => clearTimeout(timer);
396+
}, []);
397+
355398
// Use the same card container and header style as Action
356399
return (
357400
<div className={clsx(
@@ -384,7 +427,20 @@ export function StreamingAction({
384427
{/* Loading state body */}
385428
<div className="px-3 py-4 text-xs text-zinc-500 dark:text-zinc-400 flex items-center gap-2 min-h-[32px]">
386429
<Spinner size="sm" />
387-
<span>Loading...</span>
430+
<span className="animate-pulse">
431+
{loadingStage === 'fetching'
432+
? (action.config_type === 'agent'
433+
? `Creating agent...`
434+
: action.config_type === 'pipeline'
435+
? `Creating pipeline...`
436+
: `Fetching ${action.config_type} definition...`)
437+
: (action.config_type === 'agent'
438+
? `Configuring agent...`
439+
: action.config_type === 'pipeline'
440+
? `Configuring pipeline...`
441+
: `Configuring ${action.config_type}...`)
442+
}
443+
</span>
388444
</div>
389445
</div>
390446
);

0 commit comments

Comments
 (0)