Skip to main content

1. Run a simple agent

A model, a system prompt, a user prompt. No tools. The model answers from what it knows.
Three names. id is the session: Albus creates it on the first run and continues it on every later run, so the next prompt to support-1234 sees this one. agent_name groups runs into an agent; the agent object is its configuration. Albus supplies the model until you bring your own key. The current date and time are prepended to system_prompt; omit it and a server default applies.

2. Make the run retry-safe

Add an invocation_key. Retrying with the same key re-attaches to the same run instead of starting a new one, so a network failure, a 504 from a long wait, or a lost response costs nothing.
Over HTTP the key is the Idempotency-Key header. It is unique in your organization and is how you read the run back later: GET /traces/{invocation_key}. The response always returns the effective key in Idempotency-Key, including when the server generated it. Session id. Match ^[0-9a-zA-Z._:-]+$, 2–100 characters. Use an id you already have: the ticket (support-1234), the pull request (pr-987), the job (nightly:2026-08-11). Then you can find the session without storing a mapping, and the conversation continues where the work does. Invocation key. Derive it from the thing that must happen exactly once: the id of the event that triggered the run, or the session id plus a turn counter (support-1234-triage-1). Do not use a timestamp or a random value generated on each retry; each one starts a new run, which is exactly what the key is meant to prevent. The same key re-attaches even to a failed run. Reuse the key to recover a lost response; use a new key to run again.

3. Add web search and a terminal

Add the two built-in tools. The agent can now search the web and run commands in a persistent Linux sandbox, and the model decides when to call each. Runs take longer and answers are grounded in what the tools return.
tools is an allowlist. Include a tool’s block to offer it; leave it out and the model never learns the tool exists. A prompt that says “do not run commands” is not a substitute: the model can ignore instructions, but it cannot call a tool it was never given. web_search appears in traces as WEB_SEARCH, terminal as TERMINAL. Details in Built-in tools. Tool calls take steps. Set max_steps to cap how many model steps a run may take before it stops.

4. Add a secret and an MCP server

Give the agent your own tools through an MCP server, authenticated with a secret. The agent can now act on your systems — here, search GitHub issues — and the credential never appears in the configuration, the audit log, or a revision. Store the credential first. Secrets are administration, so the CLI is the right tool. The value is the full header value the server expects, Bearer included:
Reads return the value masked to its last three characters; nothing returns the full value. Names are /-separated segments of [a-zA-Z0-9_-]. Group them like files. Reference the secret from the agent as albus.sh/secrets/<name>:
Albus connects to the server for the run, discovers its tools, offers them to the model, and dispatches the calls. Nothing runs on your machine. The server must speak Streamable HTTP at a public http(s) URL; stdio servers need an HTTP front. A server you host yourself needs no headers entry: when headers has no Authorization entry, Albus sends a signed identity token, which your server verifies against your organization’s issuer. See Authenticate Albus to your MCP server. References resolve when the run starts, not when the request is validated. A reference to a missing secret fails the run, not the request, so create the secret first. Rotate with albus secrets update: references keep working, the next run picks up the new value, and the agent configuration does not change.

5. Configure memory

Add a memory group. What the agent learns now outlives the session: every run configured with the same group reads the same memories, whichever session it runs in, and writes new ones at the points you list.
generation says when memories are written: end_of_invocation after the run answers, agent whenever the agent decides mid-run that something is worth keeping. Scope a group however you like: one per customer, per team, per agent. Without memory, a session still remembers its own last 1000 messages; memory carries knowledge between sessions. Read and prune a group with GET /memories?group=support and DELETE /memories?group=support, or in the console under Memories. More in Built-in tools.

6. Read the trace and iterate

Every run is recorded as a trace: the run, each step, the model call in each step, and the tool calls it requested, as spans with inputs, outputs, timings, and token usage. The trace is how you find out what the agent did, and the fastest loop for fixing a prompt or a tool. Point a coding agent at it.
Span ids read as a path: inv4 is the fourth run of the session, inv4.attempt1.step1.tool1 the first tool call the first step requested. A model_call span’s input is exactly what the model was given and its output what it said, including the tool calls it asked for. A tool_call span’s input is the arguments and its output the tool’s result. Long payloads are cut with an [omitted: …] marker and carry the full byte count and SHA-256. Questions to ask a trace:
  • Did the agent call the tool you expected? If WEB_SEARCH fires where github__search_issues should have, the tool’s description (from the MCP server) or your system_prompt did not make the choice obvious. Name the tool and when to use it in the prompt, or tighten allowed_tools.
  • Did the tool give the agent what it needed? Read the tool_call output. A tool that returns 40 KB of JSON for a one-line answer wastes steps and tokens. A tool that returns an error the model cannot act on gets retried. Fix the tool, not the prompt.
  • Where did the steps go? Count step spans and read usage on each model_call. The same tool called in a loop with slightly different arguments means the task is underspecified. A max_steps stop means the budget or the prompt is wrong.
  • Why did it fail? A FAILED span carries error; the run carries a failure. A retried run has more than one attempt. Pass --attempts all to see the superseded ones; their tool calls still had their effects.
albus traces list shows runs across sessions, newest first, filtered by --agent-name, --agent-revision, --status, --session, --since, and --until. --status FAILED on an agent name is the first thing to look at when a job goes wrong. Spans are kept for 90 days. The console shows the same under Traces, one run per /traces/<invocation_key>. Change the prompt or a tool, run again with a new invocation key, compare the traces. Which raises what “change” means.

7. Every change is a revision

You never create an agent. You name one on a run and Albus records the configuration. Every distinct agent object under one agent_name is a revision, identified by a hash of the configuration. Each step in this guide created a new revision of support-triage; running the same configuration again reuses the existing one.
get_agent returns the current revision’s full configuration plus every revision, newest first. get_agent_revision returns one revision’s exact model, prompt, tools, MCP servers, and memory. In the console, Agents lists them; each revision lives at /agents/<name>/revisions/<revision>. Every session response carries session.agent_revision. Every trace and audit event carries agent_revision. GET /traces?agent_name=…&agent_revision=… lists every run of one configuration. That is the link from an answer you do not like back to the configuration that produced it. Keep agent_name stable per job (support-triage, pr-reviewer), not per run or per customer, so the revision list is the agent’s history. Per-run identity belongs in the session id. Record the revision next to your own results. A revision is configuration only; credentials are references, so rotating a secret does not create one.

8. The audit log

The audit log is the security record of a session: an immutable, time-ordered account of every run, model call, and tool call, arguments and results included, and how each run ended. A trace is for understanding and iterating. The audit log answers what did this agent do, on whose request, with which configuration.
Events created before the rename to invocation_* keep their old run_* names. Every event carries session_id, the invocation_key it belongs to, the agent_revision that ran, event_time, and a payload shaped by its type. Model output, tool output, and tool arguments are stored up to 32 KiB each, with the complete value’s byte count, SHA-256 digest, and a truncation flag (contentBytes, contentSha256, contentTruncated), so a stored value can be checked against the original. Secrets never appear: references resolve at run time and the values are not written anywhere the API returns.
Page with --after/--limit (default 100), passing the response’s next_cursor as the next after. The log is per session. For the same events across sessions, filtered by agent, revision, status, or time, use traces.

Clean up

Where next