Skip to main content
Once an agent is live you stop asking “does it work?” and start asking “what did it just do, and what did it cost?”. Agentor answers both from one place: the stream of events every run emits. Those events come back on the result object, so your own code can read them.

Read a run in code

agent.run() and await agent.arun() return a RunResult. It carries the answer and the evidence:
str | BaseModel | None
The agent’s answer. A parsed model instance when output_type is set, None if the run did not finish.
'completed' | 'max_turns' | 'failed'
How the run ended. Always check this before trusting final_output.
str | None
Why the run did not complete. None on success.
Usage
input_tokens, output_tokens, and total_tokens summed across every model call in the run.
list[dict]
The conversation as the model saw it — user, assistant, and tool messages. Pass it back into arun() to continue the conversation.
list[Event]
Every step: run_start, generation, tool_call, tool_result, message, run_end.

Track token usage

For per-call detail, walk the generations:

See which tools ran

result.tool_calls lists the calls the model asked for, with the arguments it chose:
For what each tool actually returned, read the results:

Tell the three endings apart

A run that did not produce an answer is not automatically an exception. Check status:
The agent answered. final_output is set, error is None.

Failing tools do not kill the run

A tool that raises does not end the run. The error text goes back to the model, which can try something else or explain the gap. If the same tool keeps failing, it is withdrawn after two attempts so it cannot burn the remaining turns:
The tool ran twice, then stopped being offered. Both failures are visible in the run:
The failure budget defaults to two attempts per tool. Adjust it per agent with Agentor(..., max_tool_failures=3) — higher for tools that are legitimately flaky, lower to fail fast.

Keep a copy of every run

A store keeps every run — and lets you finish one if the process dies:
Every event lands in runs/<run_id>.jsonl as it happens, so you can replay a run later, and agent.resume(run_id) can pick up an interrupted one.

Watch a run as it happens

For live progress rather than a post-mortem, stream it:
See the streaming guide for the full event shape.

Next steps

Durable runs

Save runs to disk and resume them after a crash.

Streaming

Show progress to users while the agent works.

Deployment

Serve the agent as an API.
Last modified on November 3, 2026