context.agents.run(...) to add multi-step reasoning to a server-side workflow. An interactive CLI drives and inspects the same agents.
Define an agent
Agents are off until the config declares at least one[[agents]] table:
Any key not listed above passes through to generation, so
temperature, top_p, and friends work as written.
Agent definitions are validated at startup, not on first run: an unknown buttress/ model, a missing prompt file, a malformed tool name, or a duplicate agent name stops the server with an error rather than silently dropping the agent.
Global options
[agents_options] applies to every agent:
Models
model is provider/model-id, split on the first slash — so the model id itself may contain slashes.
buttress/<repo_id> targets a model this server already hosts. The id must match the repo_id of a configured ggml-llm or mlx-llm [[generators]] entry, and the server checks that at startup. Traffic reaches the generator through an in-process loopback — no socket, and no extra configuration. Enabling [openai_compat] is not required; that key still governs only the external HTTP route.
anthropic/…, openai/…, google/… — authenticated by that provider’s usual environment variable (ANTHROPIC_API_KEY, OPENAI_API_KEY, …). Set it in [env] or in the process environment.
OAuth-based provider logins are not supported. A hosted provider needs an API key in the environment.
Tools
tools lists local function names explicitly. Each tool call runs through the normal functions executor, so a tool gets the same lazy reload, scratch directory, spawn tracking, and meta.timeout deadline it would get over HTTP or MCP — and the function’s meta.parameters JSON Schema is what the model sees.
Aborting a run aborts its in-flight tool calls and the processes those calls spawned.
A listed function that does not exist fails the run rather than letting a headless automation improvise around a missing capability.
MCP servers
[agents.mcp_servers.<name>] adds an MCP server’s tools alongside the local functions. Give each server exactly one of url (Streamable HTTP) or command (stdio):
mcp__github__create_issue — so they cannot collide with local function names. Servers connect lazily on the first run that needs them, and a server that will not connect fails the run unless it is marked optional = true, in which case the agent runs without its tools.
Set exposure to choose how a server’s tools reach the model, and tool_exposure to override it for single tools, keyed by exact tool name or a * pattern. An exact name wins over a pattern; among patterns, the first match wins.
codemode or deferred on an agent without codemode = true stops the server at startup.
Local devices
local_devices = true gives one agent two built-in tools for reaching BRICKS devices on the LAN. They work independently of local functions and MCP servers — [functions] does not have to be enabled — and they are off until you opt in:
devices_scan or devtools to tools, which accepts local function names only. Changing local_devices takes effect on the next server start.
devices_scan runs the same UDP and HTTP discovery as bricks devtools scan, on the Buttress host’s network rather than the caller’s, and also picks up local project previews relative to the config directory. Call it with {}, or narrow it:
devtools drives one device through the Chrome DevTools Protocol. Every call takes an action and an address — a hostname or IP without the port, IPv6 in brackets — plus port (default 19851):
Scan first, then address a device from the results:
passcode or a workspace DevTools accessToken when the device requires one; otherwise the connection uses the credential the device advertises for Chrome Inspect. Buttress never reads the host’s BRICKS CLI login and never mints tokens of its own.
Each call opens and closes its own CDP connection, and a device accepts one inspector at a time — so issue calls sequentially, and keep other DevTools clients off the device while an agent is working. Aborting a run closes any open connection; a scan already in flight finishes its bounded sweep before reporting the abort.
Codemode
codemode = true adds a codemode tool to one agent. With it, the model writes a short JavaScript program that calls the agent’s other tools — local functions, MCP tools, and the local device tools — instead of calling them one at a time. It can run calls in parallel, chain one result into the next call, or filter a large result down before it reaches the context. Only what the script outputs goes back to the model.
- Find and call MCP tools that are kept out of the model’s tool list with
exposure = "codemode". See MCP servers - Run classifier models with the agent’s provider credentials
- Keep small values for later scripts in the same session
codemode takes effect on the next server start.
Run an agent
From a local function
This is the primary surface. Every configured agent is reachable throughcontext.agents:
A run inherits the calling function’s lifetime and deadline:
context.signal — the function’s meta.timeout expiring, or the caller disconnecting — aborts the run and its tool calls. Agent loops are slower than ordinary function calls, so raise meta.timeout, or move the work into a daemon, which has no deadline.
Agent progress mirrors onto the function’s own SSE stream as agent events, so an SSE caller of the function sees the agent working without extra wiring.
Every method throws when the server has no [[agents]] configured.
Over HTTP
AGENT_RUN_FAILED with the sessionId attached, so the transcript is still reachable. An aborted run answers 499; other failures answer 500. Unknown agents and sessions answer 404 NOT_FOUND.
Streaming responses carry slimmed agent events: partial assistant messages and full tool results are omitted, because they would dwarf the stream. Fetch the transcript from the sessions endpoint when you need the complete record.
From the CLI
bricks-buttress agent is a streaming chat client for an agent on a running server. Point it at the same config the server uses and it finds the port and the local token itself:
The chat streams text, thinking, and tool calls as they happen. In the chat,
/exit quits, /new starts a fresh session, and Ctrl+C aborts the current run — a second Ctrl+C quits.
Run result
context.agents.run and POST /agents/<name>/run both resolve to:
stopReason is one of end_turn (the agent answered), max_turns, token_budget, aborted, or error. Treat anything but end_turn as an incomplete answer.
Sessions
Every run belongs to a session. OmitsessionId and the run starts a new one; pass it back to continue the conversation; add fork: true alongside it to branch into a fresh session that records its parent, leaving the original untouched.
Sessions are JSONL files under sessions_dir, scoped by agent name, and written as the run streams — so a run that was aborted or timed out still leaves a continuable transcript.
Runs on the same session queue behind each other; different sessions run in parallel.
A retention sweep prunes sessions by age (session_max_age) and count (session_max_count, per agent).
Sessions are scoped by the agent’s
name. Renaming an agent orphans its existing sessions — they stay on disk but the renamed agent will not list or continue them.Security
/agents authenticates like the functions surface, not like the open inference endpoints:
- A bound server requires a workspace access token. See workspace binding.
- An unbound server rejects remote calls entirely, unless
[agents_options] allow_unauthenticated = true. - Cross-site browser requests are always rejected.
runtime-token file next to sessions_dir, with mode 0600. Same-host tools — the CLI above — read it and authenticate automatically, bound or not.
Agent definitions are trusted input, exactly like the config file and function files. An agent is only as safe as the functions, MCP servers, and device access you hand it: a model is choosing when to call them, so give an agent the narrowest tool list that does its job.
A bound server cannot mint workspace tokens for itself — the loopback to buttress/ models is authorized by an internal token instead, and never by workspace credentials.
Samples
The server package shipsconfig/function-samples/run-agent.ts, a local function that drives a configured agent and returns its conclusion, session id, turn count, and stop reason. config/sample.toml carries a commented [[agents]] block. See local functions for the rest of the samples.
Next steps
Local functions
Write the functions an agent uses as its tools.
Configuration
The full TOML reference, including the generators agents run on.