Install any skill in seconds. Free to start, no credit card required.
Get Started Free →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`.
.claude/skills/butterbase-ai-agents/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 62% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 8% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 60% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 26% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 72% | 0% |
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.
visibility: public or authenticated).list_agent_runs, then get_agent_run).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.
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], optional temperature (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).
| 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.
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.
| 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). |
agents/<name>.json) — versioning it in git makes templates portable and lets butterbase repo push carry it to clones.validate_agent_spec (MCP) or pass the file to a validate_agent_spec call. Surface any Zod issues to the user with field paths.agent_mcp_servers table (MCP-tool wrapper TBD; use the dashboard or POST /v1/<app_id>/agent-mcp-servers directly). Wait for status: healthy.create_agent with name, graph_spec, default_model, access fields. If visibility ≠ 'private' and any write tool is reachable, require the user to explicitly say "yes, I acknowledge" and set safety_acknowledged: true.invoke_agent with a small input. Poll get_agent_run until terminal. Show the user the run timeline (steps, tool calls, final output).update_agent is a PATCH. Pass only changed fields. Bumping graph_spec revalidates; runs in flight against the old spec finish unmolested.update_agent { status: 'disabled' } — new runs return 403, existing runs keep going.list_agent_runs filtered by agent name, then get_agent_run(run_id) for the event timeline.error.code: validation_failed (spec issue), tool_error (named tool, named arg), budget_exceeded, rate_limited, timeout.args_template with the underlying tool directly (select_rows, invoke_function, etc.) to confirm the issue is in the tool's surface, not the agent runtime.human_input_required checkpoints, resume with resume_agent_run(run_id, user_input).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.validate_agent_spec. Zod issues are clearer than the runtime errors you get from a bad spec at first invocation.visibility: public with write tools and no rate limits. The control plane will refuse without safety_acknowledged: true, but you should also set per-IP limits and a daily budget.system_prompt or args_template. Read them from ctx.env inside a function tool instead — agent specs are visible to anyone who can read the agent.max_steps ceiling. Always cap.query_table returns empty, the calling role probably can't see the rows — check exposed_to.agents/*.json) and document recreation in the README.Other measured skills in the registry, with their headline benchmark lift.