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 go two ways. They are uploaded to Celesto as a trace you can click through, and they come back on the result object so your own code can read them.

Send runs to Celesto

Set your Celesto API key and turn tracing on for the agent — a run is only recorded when both are true:
Each run becomes one trace: an agent span, a span per model call, and a span per tool call, with timings and token counts throughout. See Tracing for setup options, private endpoints, and what each span holds.
Tests need no special handling - tracing is off unless you ask for it. To keep one run out of an agent that has it on, pass tracing=False on that call. Runs behave identically either way; only the upload is skipped.

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

Tracing is for looking at runs. A store is for keeping them — and for finishing them if the process dies:
Every event lands in runs/<run_id>.jsonl as it happens, so you can replay a run long after the dashboard has moved on, 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

Tracing

Set up Celesto tracing and learn what each span records.

Durable runs

Save runs to disk and resume them after a crash.

Streaming

Show progress to users while the agent works.

Deployment

Ship the agent, with observability already on.
Last modified on August 28, 2026