Smart Agent Teams

Run your first agent

Execute an agent run end to end on the local demo company, first simulated, then with Claude Code.

This tutorial follows one piece of work through SAT on your local demo company: you assign a task to Toni, the NoteFlow content writer, a runner claims the queued run, the agent works, and the result lands back on the task with its cost on Toni's budget. You do it twice: first with the built-in simulator, which calls no model and costs nothing real, then with Claude Code.

Before you start

  • SAT running locally with the demo company seeded. See Run SAT locally.

  • The CLI signed in to the local profile with NoteFlow as the default company:

    bun run sat -- login --email demo@example.com
    bun run sat -- company use NoteFlow
  • For the second part: Claude Code installed, signed in, and on your PATH as claude.

The examples write sat for bun run sat --. Toni is a good first agent: Toni's adapter is claude_code, Toni has no run in progress, and the task below has no project, so the runner uses a scratch folder instead of cloning the demo's placeholder repository.

Steps

Create an API key for the runner

Runners authenticate with an API key, not a password session, because agents use the runner's credential through sat.

sat apikey create runner --store

The key (sat_live_…) is printed once. --store saves it as the local profile's credential, replacing your password session, so from now on the profile signs in with the key. A key can do everything a session can except create or revoke keys; run sat login again when you need to manage keys.

Assign a task

sat tasks create "Draft the v1 release notes" --assignee Toni \
  --description "Five short bullet points on what NoteFlow v1 includes, written for the waitlist."
sat runner status

The task gets the next key; with a fresh seed that is NF-21. Because the task is todo and Toni is available (not paused, pending_approval or terminated), SAT queues a run with trigger assignment, and sat runner status lists it under Queued. In the web app, open the task: its thread shows the queued run.

Run it with the simulator

sat runner start --simulate --once

--simulate replaces every adapter with a built-in echo adapter, and --once executes what is queued now and then exits. The log looks like this:

10:42:01 runner my-laptop:41233 serving NoteFlow · simulate · concurrency 2
10:42:01 ▶ Toni · NF-21
10:42:03 ✓ Toni · NF-21 succeeded
10:42:03 runner done: 1 claimed, 1 succeeded, 0 failed, 0 stopped

Here is what happened, in order:

  1. The runner claimed the run (POST /runs/claim). The run became running and Toni became running.
  2. The runner moved NF-21 from todo to in_progress, as Toni.
  3. It prepared Toni's workspace, a scratch folder at ~/.local/share/sat/workspaces/nf/agents/toni.
  4. The echo adapter wrote three steps to the transcript and reported 100 input tokens, 50 output tokens and a cost of 1 cent.
  5. The runner posted the final reply as a comment from Toni, then moved the task to in_review.
  6. It reported the run as succeeded. Toni went back to idle, and the 1 cent counted toward Toni's spend this month.

Look at the result:

sat tasks show NF-21          # status in_review, Toni's comment, the run
sat runs list --agent Toni --limit 1
sat runs show <run-id-prefix> # tokens, cost, summary and transcript

The transcript reads (each line is prefixed with its time):

system  Assigned NF-21
system  Claimed by runner my-laptop:41233
system  Runner my-laptop:41233 · scratch folder /Users/you/.local/share/sat/workspaces/nf/agents/toni
agent   Toni picked up NF-21 in /Users/you/.local/share/sat/workspaces/nf/agents/toni
tool    step 1/3
tool    step 2/3
tool    step 3/3

The comment on the task, and the run's summary, is "Echo: NF-21 Draft the v1 release notes done."

The seeded running runs

If the seed ran more than five minutes ago, this first claim also marks the seed's three running runs (Grace, Ken and Maya) as failed with "The process running it stopped reporting (lease expired)", and sets those agents to error. That is the lease rule freeing agents whose runner disappeared. They take work again on their next run.

Run it with Claude Code

Check that the runner can see Claude Code:

sat runner adapters

claude_code should show ready: yes. Then give Toni a real task and run only Toni's work:

sat tasks create "Write a 100-word announcement for the NoteFlow waitlist" --assignee Toni \
  --description "Save it as announcement.md and summarise it in your final message."
sat runner start --once --agents Toni --max-turns 15 \
  --claude-settings '{"permissions": {"allow": ["Bash(sat:*)"]}}'

What the flags do:

  • --agents Toni claims only Toni's runs, so nothing else in the demo starts.
  • --max-turns 15 caps the agent's turns for this run.
  • --claude-settings is passed to claude --settings. The example allows the agent to run sat commands without asking. Claude Code runs non-interactively here, in the default permission mode acceptEdits: file edits are allowed, but shell commands that are not allowed by your settings are refused. Without this rule the agent can still finish the task; it just cannot comment or move tasks itself, and the runner does that for it.

The runner starts claude -p --output-format stream-json in Toni's scratch folder, with Toni's identity (name, title, manager Maya, company mission, instructions) as the system prompt and the task, its goal chain, project and discussion as the prompt. While it works:

  • Transcript. Every 2 seconds the runner appends what the agent did: its messages (agent), tool calls such as → Write announcement.md and their results (tool). Watch it live with sat runs tail <run-id-prefix> or on the run page in the web app.
  • Lease. The runner heartbeats every 30 seconds. If you cancel the run (sat runs cancel <run-id-prefix> or Cancel run on the run page in the web app), the runner stops Claude Code immediately.
  • Agent tools. Inside the run, sat acts as Toni (the runner sets SAT_RUN_ID), so comments and task moves made by the agent are attributed to Toni in the activity log.

Review the result

When Claude Code finishes, the runner:

  • posts Toni's final message as a comment on the task,
  • moves the task to in_review (unless Toni already moved it, for example to blocked),
  • reports the run succeeded with input and output tokens and the cost Claude Code reported, rounded up to the next cent.
sat tasks show NF-22
sat agents show Toni          # budget line shows spend this month against Toni's $60.00
ls ~/.local/share/sat/workspaces/nf/agents/toni

In the web app, the task appears in Inbox under "Blocked or waiting for review". Read Toni's comment, then move the task to Done, or comment with changes and wake Toni again (sat agents wake Toni --task NF-22).

If a run brings Toni's month-to-date spend to the $60 budget, SAT pauses Toni when the run finishes and opens a budget_override approval in the inbox. Approve it with a new limit (sat approvals approve <id-prefix> --budget 100) to resume Toni.

Troubleshooting

Next steps

On this page