mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-06-12 19:55:19 +02:00
moved agents to folders
This commit is contained in:
parent
428faea4f0
commit
54b4d94637
4 changed files with 111 additions and 62 deletions
4
apps/cli/package-lock.json
generated
4
apps/cli/package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "@rowboatlabs/rowboatx",
|
||||
"version": "0.10.0",
|
||||
"version": "0.13.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@rowboatlabs/rowboatx",
|
||||
"version": "0.10.0",
|
||||
"version": "0.13.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "^2.0.44",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ Load this skill whenever a user wants to inspect, create, or update agents insid
|
|||
|
||||
**IMPORTANT**: In the CLI, there are NO separate "workflow" files. Everything is an agent.
|
||||
|
||||
- **All definitions live in \`agents/*.json\`** - there is no separate workflows folder
|
||||
- **All definitions live in \`agents/<agent_name>/\`** with separate files for config, tools, and instructions
|
||||
- Agents configure a model, instructions, and the tools they can use
|
||||
- Tools can be: builtin (like \`executeCommand\`), MCP integrations, or **other agents**
|
||||
- **"Workflows" are just agents that orchestrate other agents** by having them as tools
|
||||
|
|
@ -20,23 +20,39 @@ Load this skill whenever a user wants to inspect, create, or update agents insid
|
|||
4. Data flows through tool call parameters and responses
|
||||
|
||||
## Agent format
|
||||
\`\`\`
|
||||
agents/
|
||||
agent_name/
|
||||
config.json # description + optional model/provider
|
||||
instructions.md # agent instructions
|
||||
tools.json # tool definitions
|
||||
\`\`\`
|
||||
|
||||
**config.json**
|
||||
\`\`\`json
|
||||
{
|
||||
"name": "agent_name",
|
||||
"description": "Description of the agent",
|
||||
"model": "gpt-5.1",
|
||||
"instructions": "Instructions for the agent",
|
||||
"tools": {
|
||||
"descriptive_tool_key": {
|
||||
"type": "mcp",
|
||||
"name": "actual_mcp_tool_name",
|
||||
"description": "What the tool does",
|
||||
"mcpServerName": "server_name_from_config",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"param1": {"type": "string", "description": "What the parameter means"}
|
||||
}
|
||||
"model": "gpt-5.1"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
**instructions.md**
|
||||
\`\`\`md
|
||||
Instructions for the agent
|
||||
\`\`\`
|
||||
|
||||
**tools.json**
|
||||
\`\`\`json
|
||||
{
|
||||
"descriptive_tool_key": {
|
||||
"type": "mcp",
|
||||
"name": "actual_mcp_tool_name",
|
||||
"description": "What the tool does",
|
||||
"mcpServerName": "server_name_from_config",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"param1": {"type": "string", "description": "What the parameter means"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -88,53 +104,51 @@ Load this skill whenever a user wants to inspect, create, or update agents insid
|
|||
|
||||
**1. Task-specific agent** (does one thing):
|
||||
\`\`\`json
|
||||
{
|
||||
"name": "summariser_agent",
|
||||
"description": "Summarises an arxiv paper",
|
||||
"model": "gpt-5.1",
|
||||
"instructions": "Download and summarise an arxiv paper. Use curl to fetch the PDF. Output just the GIST in two lines. Don't ask for human input.",
|
||||
"tools": {
|
||||
"bash": {"type": "builtin", "name": "executeCommand"}
|
||||
}
|
||||
}
|
||||
// agents/summariser_agent/config.json
|
||||
{ "description": "Summarises an arxiv paper", "model": "gpt-5.1" }
|
||||
|
||||
// agents/summariser_agent/instructions.md
|
||||
Download and summarise an arxiv paper. Use curl to fetch the PDF. Output just the GIST in two lines. Don't ask for human input.
|
||||
|
||||
// agents/summariser_agent/tools.json
|
||||
{ "bash": { "type": "builtin", "name": "executeCommand" } }
|
||||
\`\`\`
|
||||
|
||||
**2. Agent that delegates to other agents**:
|
||||
\`\`\`json
|
||||
{
|
||||
"name": "summarise-a-few",
|
||||
"description": "Summarises multiple arxiv papers",
|
||||
"model": "gpt-5.1",
|
||||
"instructions": "Pick 2 interesting papers and summarise each using the summariser tool. Pass the paper URL to the tool. Don't ask for human input.",
|
||||
"tools": {
|
||||
"summariser": {
|
||||
"type": "agent",
|
||||
"name": "summariser_agent"
|
||||
}
|
||||
}
|
||||
}
|
||||
// agents/summarise-a-few/config.json
|
||||
{ "description": "Summarises multiple arxiv papers", "model": "gpt-5.1" }
|
||||
|
||||
// agents/summarise-a-few/instructions.md
|
||||
Pick 2 interesting papers and summarise each using the summariser tool. Pass the paper URL to the tool. Don't ask for human input.
|
||||
|
||||
// agents/summarise-a-few/tools.json
|
||||
{ "summariser": { "type": "agent", "name": "summariser_agent" } }
|
||||
\`\`\`
|
||||
|
||||
**3. Orchestrator agent** (coordinates the whole workflow):
|
||||
\`\`\`json
|
||||
// agents/podcast_workflow/config.json
|
||||
{ "description": "Create a podcast from arXiv papers", "model": "gpt-5.1" }
|
||||
|
||||
// agents/podcast_workflow/instructions.md
|
||||
1. Fetch arXiv papers about agents using bash
|
||||
2. Pick papers and summarise them using summarise_papers
|
||||
3. Create a podcast transcript
|
||||
4. Generate audio using text_to_speech
|
||||
|
||||
Execute these steps in sequence.
|
||||
|
||||
// agents/podcast_workflow/tools.json
|
||||
{
|
||||
"name": "podcast_workflow",
|
||||
"description": "Create a podcast from arXiv papers",
|
||||
"model": "gpt-5.1",
|
||||
"instructions": "1. Fetch arXiv papers about agents using bash\n2. Pick papers and summarise them using summarise_papers\n3. Create a podcast transcript\n4. Generate audio using text_to_speech\n\nExecute these steps in sequence.",
|
||||
"tools": {
|
||||
"bash": {"type": "builtin", "name": "executeCommand"},
|
||||
"summarise_papers": {
|
||||
"type": "agent",
|
||||
"name": "summarise-a-few"
|
||||
},
|
||||
"text_to_speech": {
|
||||
"type": "mcp",
|
||||
"name": "text_to_speech",
|
||||
"mcpServerName": "elevenLabs",
|
||||
"description": "Generate audio",
|
||||
"inputSchema": { "type": "object", "properties": {...}}
|
||||
}
|
||||
"bash": { "type": "builtin", "name": "executeCommand" },
|
||||
"summarise_papers": { "type": "agent", "name": "summarise-a-few" },
|
||||
"text_to_speech": {
|
||||
"type": "mcp",
|
||||
"name": "text_to_speech",
|
||||
"mcpServerName": "elevenLabs",
|
||||
"description": "Generate audio",
|
||||
"inputSchema": { "type": "object", "properties": { "...": "..." } }
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
|
@ -142,10 +156,10 @@ Load this skill whenever a user wants to inspect, create, or update agents insid
|
|||
**To run this workflow**: \`rowboatx --agent podcast_workflow\`
|
||||
|
||||
## Naming and organization rules
|
||||
- **All agents live in \`agents/*.json\`** - no other location
|
||||
- Agent filenames must match the \`"name"\` field exactly
|
||||
- When referencing an agent as a tool, use its \`"name"\` value
|
||||
- Always keep filenames and \`"name"\` fields perfectly aligned
|
||||
- **All agents live in \`agents/<agent_name>/\`** with \`config.json\`, \`instructions.md\`, and \`tools.json\`
|
||||
- Directory name must match the agent name exactly
|
||||
- When referencing an agent as a tool, use its directory/agent name
|
||||
- Keep directory names aligned with any references inside tools.json
|
||||
- Use relative paths (no \${BASE_DIR} prefixes) when giving examples to users
|
||||
|
||||
## Best practices for multi-agent design
|
||||
|
|
|
|||
7
apps/cli/src/application/entities/agent-config.ts
Normal file
7
apps/cli/src/application/entities/agent-config.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { z } from "zod";
|
||||
|
||||
export const AgentConfig = z.object({
|
||||
description: z.string(),
|
||||
model: z.string().optional(),
|
||||
provider: z.string().optional(),
|
||||
});
|
||||
|
|
@ -14,6 +14,7 @@ import { AskHumanRequestEvent, RunEvent, ToolPermissionRequestEvent, ToolPermiss
|
|||
import { BuiltinTools } from "./builtin-tools.js";
|
||||
import { CopilotAgent } from "../assistant/agent.js";
|
||||
import { isBlocked } from "./command-executor.js";
|
||||
import { AgentConfig } from "../entities/agent-config.js";
|
||||
|
||||
export async function mapAgentTool(t: z.infer<typeof ToolAttachment>): Promise<Tool> {
|
||||
switch (t.type) {
|
||||
|
|
@ -165,9 +166,36 @@ export async function loadAgent(id: string): Promise<z.infer<typeof Agent>> {
|
|||
if (id === "copilot") {
|
||||
return CopilotAgent;
|
||||
}
|
||||
const agentPath = path.join(WorkDir, "agents", `${id}.json`);
|
||||
const agent = fs.readFileSync(agentPath, "utf8");
|
||||
return Agent.parse(JSON.parse(agent));
|
||||
const agentDir = path.join(WorkDir, "agents", id);
|
||||
if (!fs.existsSync(agentDir)) {
|
||||
throw new Error(`Agent directory not found: ${agentDir}`);
|
||||
}
|
||||
|
||||
const instructionsPath = path.join(agentDir, "instructions.md");
|
||||
if (!fs.existsSync(instructionsPath)) {
|
||||
throw new Error(`Missing instructions.md for agent '${id}'`);
|
||||
}
|
||||
const instructions = fs.readFileSync(instructionsPath, "utf8");
|
||||
|
||||
const toolsPath = path.join(agentDir, "tools.json");
|
||||
const tools = fs.existsSync(toolsPath)
|
||||
? JSON.parse(fs.readFileSync(toolsPath, "utf8"))
|
||||
: undefined;
|
||||
|
||||
const configPath = path.join(agentDir, "config.json");
|
||||
if (!fs.existsSync(configPath)) {
|
||||
throw new Error(`Missing config.json for agent '${id}'`);
|
||||
}
|
||||
const config = AgentConfig.parse(JSON.parse(fs.readFileSync(configPath, "utf8")));
|
||||
|
||||
return Agent.parse({
|
||||
name: id,
|
||||
provider: config.provider,
|
||||
model: config.model,
|
||||
description: config.description,
|
||||
instructions,
|
||||
tools,
|
||||
});
|
||||
}
|
||||
|
||||
export function convertFromMessages(messages: z.infer<typeof Message>[]): ModelMessage[] {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue