Skip to main content

Agent Runs from Claude Code: Workflow Runs, Facts and Usage

The agent-farm MCP server: a run-centric tool set over core's agent_runs for developers and project managers, with the workflow engine as the run origin, scoped to the caller's own runs and projects, with the workflow inbox and per-person usage.

The agent-farm MCP server gives developers and project managers the run lifecycle from inside Claude Code or Cowork: start a workflow run, follow the headless agent steps it queues, read their event streams and recorded facts, cancel them, answer the decisions the workflow is waiting on, and read usage for themselves or one of their projects. It sits beside the admin systemprompt server on port 5011 and is scoped to the user OAuth scope. The workflow engine itself is described in Workflow Orchestration; this server is the developer-facing way in.

Who reaches it

Entitlement is declared in services/access-control/rules.yaml like every other entity. The astound-engineering workspace, its plugin, the agent_farm_runs skill and the mcp_server/agent-farm entity are closed by default and allowed to the developer, project_manager, admin, platform_admin and super_admin roles. This server is not the admin plane: project_manager is named here because the server scopes every run tool itself.

The role band only decides who sees the server. Inside it, every run tool applies one rule:

  • a person reaches a run they launched, or that ran as them, including a step that ran as a workflow's service account on a run they started;
  • a person reaches every run of a project they belong to;
  • an administrator reaches every run.

Anything else is refused with a Forbidden: error that names the run. The scope word is the same on every listing tool: mine, project, or all, and all is refused without an administrator role.

Tools

Tool Read-only What it does
run_start no Start a workflow definition's manual trigger as yourself; returns the workflow run id at once
run_status yes One agent run's lifecycle state, timings, tokens, cost, error class
run_events yes A page of the run's event stream, by seq
run_cancel no Cancel the workflow run a step belongs to, then the step
run_list yes Runs the caller may see, newest first, with recorded facts; workflow_run and definition narrow it
run_facts yes Everything recorded about one run, plus the workflow run's decisions, effects and history
run_stats yes Rollups over 24h, 7d or 30d, by status, error class and origin kind
workflow_inbox yes The open decisions addressed to a role you hold
workflow_decide no Answer one: approve, request_changes, reject or cancel
analytics_costs yes Spend over a window for the caller or a project
analytics_requests yes Gateway requests, failures, denials, latency, by model
analytics_skills yes Skill adoption and the conversations it reached
analytics_tools yes MCP tool executions by server and tool
catalog_list yes What the caller's access grants

Every input is flat: strings and numbers with defaults, so a client never has to guess a flag. Nothing here is model-judged: run_facts reports what the tables recorded and nothing else.

A run from start to facts

run_start       {"origin": "workflow", "definition": "core-dev", "context_json": "{\"jira_key\":\"ENG-12\"}"}
run_list        {"scope": "mine", "workflow_run": "<origin_run_id>"}
run_status      {"run_id": "<id>"}          until terminal
run_events      {"run_id": "<id>", "after_seq": 0}
run_facts       {"run_id": "<id>"}
workflow_inbox  {}
workflow_decide {"decision_id": "<id>", "outcome": "approve"}

run_start goes through the workflow engine's own trigger service, so the definition's trigger roles, required context keys, variant and project rules are resolved exactly as the console's Start button resolves them. The engine then queues the run's agent steps; the tool never waits for them.

run_facts is the record the tables hold: outcome, tokens, reported and metered cost, tool use counts by name, hook and governance decisions, structured output and whether it matched the schema the request asked for, and the workspace diff summary. A step's project and launcher come from its workflow run (workflow_runs.project_id and initiated_by), which is how a step that ran as a service account still belongs to the person who started the workflow.

Connecting from Claude Code

MCP servers are reached through the gateway, never on their own port: the server URL is https://<your instance>/api/v1/mcp/agent-farm/mcp. A personal access token (PAT) is not accepted there directly; exchange it for a bridge token first and present that as the bearer:

curl -s -X POST https://<your instance>/v1/auth/bridge/pat \
     -H "Authorization: Bearer <pat>" -H "Content-Type: application/json" -d '{}'
claude mcp add --transport http agent-farm https://<your instance>/api/v1/mcp/agent-farm/mcp \
     --header "Authorization: Bearer <bridge token>"

The bridge does all of this for you: a signed-in Claude Code or Cowork session that holds the astound-engineering workspace receives the server from its manifest with the token already attached. A call made straight to the server's port fails with Invalid request context headers by design.

Operating it

The server is an internal MCP binary, systemprompt-mcp-agent-farm, declared in services/mcp/agent-farm.yaml and built with the workspace. On this instance it is compiled with the workflows feature on, which links the workflows crate; the farm feature of the shared source is off because this instance has no agent-farm domain. Access audit rows land in user_activity like every other server's; tool usage lands in the same ledger the admin console reads.