Skip to content
Pilotoo
v0.1

The life of a run

A run is one execution of an agent on a conversation. This page follows one from the composer to the last event, so you know which package does what and where to look when something goes wrong.

client server runtime
| run:start -----------> | |
| | validate, RUN_STARTED |
| | -------------------------> | build or reuse the graph
| | <-------- events --------- | model + tools
| <------ run:event ------ | number, broadcast, buffer |
| ... | |
| <--- RUN_FINISHED ----- | |
  1. The chat UI renders the composer. chat-core records the message under an id it mints itself and checks that a command can still reach the server before it consumes the draft.
  2. chat-core sends run:start through the transport the app provided.
  3. The gateway validates the command against chat-protocol. It rejects a duplicate message or an unknown conversation, names the conversation from its first message, and joins the sender’s socket to the thread room.
  4. The gateway emits RUN_STARTED and hands the run to agent-runtime.
  5. The runtime finds the agent definition and the profile it names, keeps the tools the agent lists that are registered, mounts its skills and builds the graph. The graph is cached per tenant and agent, and rebuilt when the definition, the profile or a subagent changes.
  6. The graph runs. Text deltas and tool calls are drained concurrently, so parallel tool calls stay parallel.
  7. The gateway gives each event the run’s next sequence number, wraps it in an envelope that names the thread, broadcasts it to the room and appends it to a replay buffer.
  8. chat-core validates every envelope and folds it into the view model. An event type it does not know is counted and ignored.
  9. The run ends with RUN_FINISHED, RUN_CANCELLED or RUN_ERROR. The checkpoint has already stored the messages, so nothing is saved twice.

A second window, or a reload, asks for thread:messages. It receives the checkpointed history plus the replay of the run in flight, and joins the thread room. The next envelope it receives continues the last one it was given, so the screen is whole without a special case.

A run can stop and wait: for a human to approve an action, or for a blocking client tool to answer. The gateway emits INTERRUPT then RUN_PAUSED. The client shows the question and answers with run:resume, and the same run carries on.

When an orchestrator delegates with the task tool, the server runs the subagent on a child conversation with the same owner. Opening the child is like switching to another thread: history, replay and live run.

  • When a task nobody is awaiting finishes, the parent gets a turn nobody typed, marked as a task result.
  • On a thread where a run is writing, a new run:start is queued and starts when the run is done.
  • Tasks left running when the server restarts become interrupted and are reported to their parent.

The conversation list hides child conversations. Deleting the parent deletes its children.