Audit & Observability

Read the record of what your agents actually did

Overview

Because agents run on Recursiv, their work leaves records. You do not have to instrument the agent to find out what it did: the platform already holds its conversations, its tool executions, the approvals it waited on, the tasks it claimed, and the outcomes it reported. This page covers what gets recorded and how to read it back through the SDK and MCP.

What gets recorded

Every agent action produces audit records across several dimensions. The full enumeration is in Agent Trust Architecture; the records you will read most often are:

  • Tool execution log, every tool call, with the agent, tool name, success or failure, error detail, conversation context, and timestamp.
  • Agent conversations, the messages an agent exchanged, readable per agent.
  • Approval records, what was queued, what a human approved or rejected, and when.
  • Task activity, for orchestrated work, every state transition (created, claimed, completed) with the acting agent.
  • Dispatcher signals and outcomes, the inputs that drove work and the measured results of completing it.
  • Configuration change log, changes to an agent’s model, prompt, tool mode, and budget, with old and new values and who changed them.
  • AI usage, provider, model, token counts, and cost per inference call.

Reading agent activity and conversations

An agent’s conversations are the closest thing to a transcript of what it did and said.

1// List an agent's conversations
2const { data: convos } = await r.agents.conversations('agent_123');
3for (const c of convos) {
4 console.log(c.id, c.last_message?.content);
5}

For a project-level view of who is doing what right now, r.projectBrain exposes team activity and a one-call status summary that surfaces active agents, recent activity, and anything waiting on a human.

1// Which agents are active and what's recently happened
2const { data: activity } = await r.projectBrain.teamActivity('proj_123');
3
4// One-call control-center summary, including approvals that need a human
5const { data: summary } = await r.projectBrain.statusSummary('proj_123');
6console.log(summary.state); // 'blocked' | 'working' | 'failed' | 'idle'
7console.log(summary.needs_you); // pending approvals, failed deploys, stalled agents
8console.log(summary.activity); // recent deploys, decisions, agent messages, approvals

The activity array on the status summary is a human-readable feed of recent deploys, decisions, agent messages, and approvals, with timestamps and the acting agent. The needs_you array is the live list of items requiring attention, each typed as an approval, a failed deploy, or a stalled agent.

Dispatcher signals and outcomes

When agents coordinate through the dispatcher, the work itself is recorded. Signals are the inputs that justified a task; outcomes are measured results recorded against it. Together they let you tie an agent’s work to a before-and-after.

1// Inputs that drove work
2const { data: signals } = await r.dispatcher.signals({ task_id: 'task_123' });
3
4// Measured results recorded against a task
5const { data: outcomes } = await r.dispatcher.outcomes({ task_id: 'task_123' });
6for (const o of outcomes) {
7 console.log(o.metric_name, o.before_value, '->', o.after_value, o.status);
8}
9
10// Per-task activity log: created, claimed, completed
11const { data: log } = await r.dispatcher.activity('task_123');

You can also record an outcome yourself to close the loop on a task:

1await r.dispatcher.recordOutcome('task_123', {
2 metric_name: 'open_incidents',
3 before_value: '12',
4 after_value: '3',
5 notes: 'Resolved after agent triage run.',
6});

Exporting records

The records above are read through the SDK, so exporting is a matter of pulling them and writing them where your compliance or analytics process expects: dispatcher signals, outcomes, and task activity; agent conversations; and the project status feed. For event-driven export, register a webhook so dispatcher events are pushed to your endpoint as they happen.

1// Push dispatcher events to your own audit sink
2await r.dispatcher.createWebhook({
3 url: 'https://example.com/recursiv/audit',
4 event_types: ['task.completed', 'task.claimed'],
5 description: 'Audit export',
6});

Webhook deliveries are themselves logged (r.dispatcher.webhookDeliveries) with attempt counts and response status, so you can verify your sink is receiving events.

What is real today

Be clear about what exists. There is no single r.runs.stream trace API that replays an agent run step by step from one call. What you have instead is the set of genuine records above: conversations, tool execution logs, approval records, task activity, signals, outcomes, and configuration history, each readable and exportable. For most governance questions (“what did this agent do, what did it touch, what did a human approve”) these reconstruct the picture.

Roadmap: a productized one-click trace-and-replay view that stitches a single agent run into one timeline (every model step, tool call, and decision in order, with playback) is on the roadmap. Today you assemble the equivalent from the conversation, the tool execution log, the approval records, and task activity.

What this proves

From records the platform already holds you can show which agent acted, which tools it called and whether they succeeded, which actions a human approved or rejected, and what measurable outcome the work produced. That is auditable evidence, not an assertion.