Agents
Use when designing, deploying, or debugging a Butterbase Agent (declarative LLM/tool graph), registering an MCP server for tool use, or wiring access controls and rate limits. Agents are first-class app resources defined by a `graph_spec` and invoked over `/v1/<app_id>/agents/<name>/runs`.From its SKILL.md
npx -y skills add butterbase-ai/butterbase-skills --skill agentsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- reads credentialsReads from 1 credential source: `ctx.env`.
- runs commandsInstructs the agent to run 6 commands, including `butterbase agents list` and 5 more.
SKILL.md
7.0 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it
Butterbase Agents
A Butterbase agent is a declarative graph of LLM and tool nodes — not a free-running chat loop. The runtime traverses the graph, calls tools (builtin / MCP / function), and resolves the end node's output_template. State, rate limits, and budgets are enforced by the control plane.
When to use
- The user wants to add a workflow that combines an LLM with tool calls (DB writes, storage reads, MCP servers, app functions).
- The user wants to expose an agent endpoint to end users (
visibility: publicorauthenticated). - Debugging a failing agent run (look at
list_agent_runs, thenget_agent_run). - Registering an external MCP server for the agent to use.
Don't use for plain LLM chat completions — use the ai skill (manage_ai / /v1/ai/chat). Agents are for stateful, multi-step, tool-using workflows.
Concepts
graph_spec (validated by validate_agent_spec before anything is persisted)
| Field | Required | Notes |
|---|---|---|
spec_version | yes | Literal "1". |
entry | yes | ID of the first node. |
nodes | yes | Record { id → node }. |
edges | yes | [{ from, to }]. Both endpoints must exist in nodes. |
tools | yes | { builtin: [], mcp_servers: [], functions: [] } — declares what nodes can call. |
limits | yes | max_steps (1–200), max_tool_calls (0–500), max_parallel_tools (1–16), timeout_seconds (5–3600), human_timeout_seconds (60–7×24×3600). |
Node types:
llm—model,system_prompt,input_template,output_key,tools: [toolRef], optionaltemperature(0–2),max_tokens.tool—tool_ref,args_template(record),output_key.end—output_template(string; can interpolate{{output_key}}values).
toolRef is a discriminated union by source:
{ source: 'builtin', name }{ source: 'mcp', server_id, name }{ source: 'function', name }
Each may carry mode_override (read_only | read_write) and exposed_to_override (developer_only | end_user).
Builtin tools (always available, no setup)
| Name | Purpose | Args |
|---|---|---|
query_table | Select rows (RLS enforced) | table, filter, limit (≤200) |
insert_row | Insert | table, values |
update_row | Update by id | table, id, patch |
delete_row | Delete by id | table, id |
read_storage | Get object (≤5 MB) | key |
write_storage | Put object (≤1 MB b64) | key, content_base64, content_type? |
auth_user_lookup | Find a user | email OR id |
All builtins respect role: end_user runs as butterbase_user with their user id (RLS applies); developer_only runs as butterbase_service.
MCP servers
Register before referencing in graph_spec.tools.mcp_servers. Transports: sse, http, streamable_http. The control plane probes on register (calls listTools()), stores status='healthy'|'unhealthy'. Re-probe with the same endpoint after a server URL change.
Access & limits
| Field | Default | Notes |
|---|---|---|
visibility | private | private (owner only), authenticated (any app user), public (anyone, with rate limits). |
max_runs_per_user_per_hour | null | null = unlimited. |
max_runs_per_ip_per_hour | null | Primary public-agent throttle. |
max_runs_per_app_per_hour | null | App-wide cap. |
daily_budget_usd | null | Hard kill once exceeded. |
max_concurrent_runs | null | |
safety_acknowledged | false | Required true if visibility ≠ private AND any node calls a write tool (insert_row, update_row, delete_row, write_storage, or a write-mode MCP/function tool). |
Procedure
Designing a new agent
- Sketch the graph in prose first. "User asks X → LLM rephrases → query_table for context → LLM answers → end." Concrete node IDs.
- Write the spec as a JSON file in the repo (e.g.
agents/<name>.json) — versioning it in git makes templates portable and letsbutterbase repo pushcarry it to clones. - Validate without persisting — call
validate_agent_spec(MCP) or pass the file to avalidate_agent_speccall. Surface any Zod issues to the user with field paths. - Register MCP servers if used:
agent_mcp_serverstable (MCP-tool wrapper TBD; use the dashboard or POST/v1/<app_id>/agent-mcp-serversdirectly). Wait forstatus: healthy. - Create —
create_agentwith name, graph_spec, default_model, access fields. Ifvisibility ≠ 'private'and any write tool is reachable, require the user to explicitly say "yes, I acknowledge" and setsafety_acknowledged: true. - Smoke —
invoke_agentwith a small input. Pollget_agent_rununtil terminal. Show the user the run timeline (steps, tool calls, final output).
Editing
update_agentis a PATCH. Pass only changed fields. Bumpinggraph_specrevalidates; runs in flight against the old spec finish unmolested.- Disabling an agent:
update_agent { status: 'disabled' }— new runs return 403, existing runs keep going.
Debugging a failing run
list_agent_runsfiltered by agent name, thenget_agent_run(run_id)for the event timeline.- Check
error.code:validation_failed(spec issue),tool_error(named tool, named arg),budget_exceeded,rate_limited,timeout. - For tool errors, re-run the same
args_templatewith the underlying tool directly (select_rows,invoke_function, etc.) to confirm the issue is in the tool's surface, not the agent runtime. - For
human_input_requiredcheckpoints, resume withresume_agent_run(run_id, user_input).
CLI
butterbase agents list/get <name>/create -f spec.json/update <name> -f patch.json/delete <name>— read/write specs from files. Useful for version-controlling agents alongside app code.
Anti-patterns
- ❌ Skipping
validate_agent_spec. Zod issues are clearer than the runtime errors you get from a bad spec at first invocation. - ❌ Setting
visibility: publicwith write tools and no rate limits. The control plane will refuse withoutsafety_acknowledged: true, but you should also set per-IP limits and a daily budget. - ❌ Putting secrets in
system_promptorargs_template. Read them fromctx.envinside a function tool instead — agent specs are visible to anyone who can read the agent. - ❌ Letting an LLM node call itself recursively without a
max_stepsceiling. Always cap. - ❌ Forgetting that builtin DB tools respect RLS. If
query_tablereturns empty, the calling role probably can't see the rows — checkexposed_to. - ❌ Treating agents as part of clone replay. Agent records are not copied when an app is cloned — bundle the spec JSON in the repo (
agents/*.json) and document recreation in the README.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 0 of the 12 instructions most mcp tooling skills give in ~1.8k tokens
Counted across 780 of the 1,136 authors here whose files we hold, read 2026-09-06
- Use Zod for input validationin 34 of 780, across 21 files
- Use stdio for local clientsin 27 of 780, across 10 files
- Restart Claude Code after configurationin 26 of 780, across 23 files
- Verify MCP server connection before using toolsin 23 of 780, across 17 files
- Define input schemas for every toolin 20 of 780, across 11 files
- Use Streamable HTTP for remote clientsin 18 of 780, across 8 files
- Pin SDK version in package.jsonin 17 of 780, across 6 files
- Keep server logic independent of transportin 16 of 780, across 6 files
- Verify SDK methods against official documentationin 15 of 780, across 5 files
- Format evaluation results as an XML filein 15 of 780, across 12 files
- Test servers using the MCP Inspectorin 15 of 780, across 14 files
- Create ten complex and independent evaluation questionsin 14 of 780, across 11 files
Said here and by no other author read
- sketch the agent graph in prose first
- write the agent spec as a JSON file
- validate the agent spec before persisting
- register external MCP servers before referencing them
- set safety_acknowledged true for public agents with write tools
- invoke the agent with small input to smoke test
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.