Skip to content

Run a workflow with realm agent

realm agent runs a workflow from start to end with a model doing the agent steps. You give it a workflow and a model provider; it calls the model, hands each answer to Realm, and carries on until the run ends or needs a person. This guide shows a run, what happens when the model answers wrongly, and how to pick up a run that stopped.

The outputs on this page come from real runs of realm agent against a local stand-in for the model, which returned answers chosen for the test. Everything on the Realm side is real.

You need:

  • a workflow with at least one agent step. This guide uses the triage workflow from Write an agent step;
  • an API key for Anthropic or OpenAI, and the name of a model that provider offers.

1. Set the provider key and choose a model

Section titled “1. Set the provider key and choose a model”

Set one of these in your shell:

Terminal window
export ANTHROPIC_API_KEY=your-key

or

Terminal window
export OPENAI_API_KEY=your-key

realm agent picks the provider from whichever key is set, and OpenAI when both are. To choose yourself, add --provider anthropic or --provider openai.

Name the model with --model <name>. It is required: Realm has no default model, because providers change their models often. Anthropic lists its models at platform.claude.com/docs/en/models/overview, and OpenAI at developers.openai.com/api/docs/models. Version 0.45.0 has a default model (gpt-4o, or claude-sonnet-4-5 for Anthropic).

The commands below use Anthropic and the model claude-sonnet-5-5; any model Anthropic lists today works. With an OpenAI key, use --provider openai --model <a model from OpenAI's list> in their place.

Run it from the workflow’s folder, with the run’s parameters as JSON:

Terminal window
realm agent --workflow ./ --register --params '{"ticket":"I was charged twice this month."}' --provider anthropic --model claude-sonnet-5-5

--register stores a copy of the workflow as part of the run, so that the other realm commands can find it afterwards.

It prints:

Realm Agent — Triage a ticket v1
Run ID: 4950eb94-37c0-41a0-8632-0b6f59cc999a
→ [agent] classify
Classify the ticket and say how urgent it is.
✓ → completed
Run complete: 4950eb94-37c0-41a0-8632-0b6f59cc999a
Result (classify):
billing (urgent: true)
The customer was charged twice this month.

Notice Result. It is the last agent step’s answer, shown through that step’s display template.

For each agent step, realm agent sends one request to Anthropic. Its system prompt holds the step’s profile, if it has one, followed by fixed instructions and the step’s schema:

You are a support lead. You classify tickets by what the customer needs next, …
You are an AI agent executing a step in a structured workflow.
Your task is described below. Call the `__realm_submit__` tool with your result, or respond with a JSON object only — no markdown, no explanation.
The JSON must conform to this schema: {"type":"object","additionalProperties":false,"required":["category","urgent","reason"], …}

Its one message is the step’s prompt, with its values filled in:

Classify this support ticket.
Ticket:
I was charged twice this month.

The request also offers the model one tool, __realm_submit__, whose input is the step’s schema; the model can answer by calling it.

If the answer does not fit the step’s schema, Realm refuses it. realm agent then asks the model again, and tells it what was wrong. In another run of the same workflow, the model first chose a category that is not on the list:

→ [agent] classify
Classify the ticket and say how urgent it is.
⚠ output rejected (VALIDATION_INPUT_SCHEMA); repairing (attempt 1/2)
✓ → completed

The second request ended with the reason for the refusal:

Your previous output was rejected by the input schema validator:
- /category: must be equal to one of the allowed values [enum]
Emit corrected JSON only, matching the schema exactly.

By default the model gets two such chances for each step. Change the number with --schema-retries <n>; 0 turns the repair off.

If the model is still wrong after the last chance, realm agent stops:

⚠ output rejected (VALIDATION_INPUT_SCHEMA); repairing (attempt 1/2)
⚠ output rejected (VALIDATION_INPUT_SCHEMA); repairing (attempt 2/2)
✗ Step 'classify' failed: Invalid input for step 'classify' after 2 schema-repair attempts

The command exits with code 1. The run itself is not ended: its phase is still running, and nothing wrong was recorded as the step’s output. The record says what happened and what it cost:

Drive failures:
2026-10-04T23:56:45.259Z classify anthropic validation_rejected after 72ms: Invalid input for step 'classify'
usage: 3 requests billed before the output was rejected — 1236 prompt tokens (totals across 3 requests), 114 output tokens (totals across 3 requests), cache read 0, wrote 0 (included in the prompt)

The usage line was added in 0.46.0. Version 0.45.0 prints the line above it and nothing about cost.

To continue a run, name it with --run-id, without --workflow. Give the provider and the model again:

Terminal window
realm agent --run-id a9fd51c7-b84d-49c9-afe5-07156edf8c27 --provider anthropic --model claude-sonnet-5-5

It prints:

Realm Agent — Triage a ticket v1
Run ID: a9fd51c7-b84d-49c9-afe5-07156edf8c27
→ [agent] classify
Classify the ticket and say how urgent it is.
✓ → completed
Run complete: a9fd51c7-b84d-49c9-afe5-07156edf8c27
Result (classify):
billing (urgent: true)
The customer was charged twice this month.

The run carries on from where it was. Steps that already completed are not run again.

The measured figures in this section were added in 0.46.0. On 0.45.0 the line reads Diagnostics: ~23 tokens | no preconditions.

realm run inspect shows, for each step the model answered, how many tokens the provider counted:

Diagnostics: ~23 tokens (estimate, step input) | 412 prompt tokens (measured, first request) | 38 output tokens | no preconditions | cache: not engaged — read 0, wrote 0 (provider-reported, 1 request)

For the run in which the first answer was refused, the same line shows two requests:

Diagnostics: ~23 tokens (estimate, step input) | 824 prompt tokens (measured, totals across 2 requests) | 76 output tokens (totals across 2 requests) | no preconditions | cache: not engaged — read 0, wrote 0 (provider-reported, totals across 2 requests)

A refused answer still costs a request. measured figures come from the provider’s own count. cache: not engaged means the provider reported that no part of the prompt was read from its cache or written to it. The estimate is Realm’s rough size of the step’s input only, and is much smaller than what was sent.

When the run reaches a human gate, realm agent prints the gate and waits. It prints one realm run respond command for each choice; run one from another terminal and the run carries on. To take the answer from Slack, see Answer gates from Slack.

--base-url <url> points realm agent at any service that speaks the OpenAI chat-completions format. Use it with --provider openai and --model <name>.

Each model request is given up to 600 seconds. Change that for a whole run with --llm-timeout <seconds>, or for one step with llm_timeout_seconds in the workflow.

After --run-id, each refusal below that ends Nothing was started. ends If run <run-id> exists, it was not changed. instead.

  • Error: realm agent requires an LLM API key. Set OPENAI_API_KEY or ANTHROPIC_API_KEY. Nothing was started. No provider key is set in this shell. A key that is empty or holds only spaces counts as not set; version 0.45.0 counted it as set. With --provider anthropic, the message names only ANTHROPIC_API_KEY (added in 0.46.0).
  • Error: --model is required: realm has no default model. ANTHROPIC_API_KEY is set, so the provider is Anthropic; name one of its models (Anthropic lists them at https://platform.claude.com/docs/en/models/overview). Nothing was started. Add --model with a model the provider lists. The message names the provider Realm chose and why; it reads differently when another key is set or --provider is given. After --run-id, it ends If run <run-id> exists, it was not changed. instead. Version 0.45.0 does not print it: it has a default model.
  • Error: --provider anthropic was given, but ANTHROPIC_API_KEY is not set or is empty (only OPENAI_API_KEY is set). Set ANTHROPIC_API_KEY, or use --provider openai with an OpenAI model. Nothing was started. The provider you named has no key in this shell. Set its key, or name the other provider and one of its models. Version 0.45.0 does not print it: it creates the run, and the first model call fails.
  • Error: one of --workflow or --run-id is required Give one of the two.
  • Error: --workflow and --run-id are mutually exclusive To continue a run, give --run-id alone.
  • Error: Workflow not found: triage — most often this run was created from a file without --register. You tried to continue a run whose workflow was never registered. Run realm workflow register ./, then try again.
  • ✗ Step 'classify' LLM call failed: Connection error. The provider could not be reached. The run is not ended; fix the connection and continue it with --run-id.
  • ✗ Step 'classify' LLM call failed: 404 {"type":"error","error":{"type":"not_found_error","message":"model: claude-sonnet-4-5"}, …, followed by the line Anthropic offers no model named claude-sonnet-4-5 to this API key. … Anthropic has no model by the name you gave. The run stays open, so continue it with realm agent --run-id <run-id> --provider anthropic --model <the right name>; running the --workflow command again starts a second run. The second line was added in 0.46.0.