Coding agents¶
What every coding-agent backend shares. Generated from src/keryx/agents/base.py.
keryx.agents.base ¶
What every coding-agent backend shares.
A backend is an AgentRunner whose open() hands back an AgentSession; everything
above that seam — the task manager, the notifier, the voice tools — sees only a
RunResult. So the protocol, the result, and the text protocol a subagent speaks back
(SPOKEN_SUMMARY: and RESTART_REQUIRED:) live here once, along with the context every
subagent is handed whichever agent runs it: the rendered system-prompt suffix, the
directory it starts in, and the workspace-mcp server that gives it Gmail and Calendar.
FakeAgentRunner is the scripted stand-in used by tests and by keryx serve --demo.
Every subagent is told (via prompts/subagent_suffix.md) to end its final message with a
SPOKEN_SUMMARY: line; extract_spoken_summary turns that into the sentence the voice
session reads out, falling back to the last paragraph when the agent forgot.
AgentRunner ¶
Bases: Protocol
Opens subagent conversations.
open
async
¶
open(task: Task, *, resume: str | None = None) -> AgentSession
Start (or resume, given a Claude session id) a conversation for task.
AgentSession ¶
Bases: Protocol
One live subagent conversation.
run
async
¶
run(prompt: str, *, on_progress: Callable[[str], Any]) -> RunResult
Run one turn to completion. Never raises: failures come back as ok=False.
send
async
¶
send(text: str) -> None
Put a follow-up into the turn that is running now.
SteerUnavailable means it was refused and nothing was delivered — the agent has
no live steer (Claude), or its turn has just ended — and the task manager re-runs
with the text instead. Any other exception is a steer that may have landed.
RunResult
dataclass
¶
The outcome of one subagent turn.
TokenUsage
dataclass
¶
What one or more turns cost in tokens, the same way for every agent.
input_tokens counts every input token, cached ones included, and cached_input_tokens
says how many of those were cache reads — Codex's meaning, and Claude's once its
uncached, cache-write and cache-read counts are summed.
extract_spoken_summary ¶
extract_spoken_summary(text: str) -> str
The sentence(s) to read out loud for a finished task.
Prefers the text after the last SPOKEN_SUMMARY: marker; falls back to the last
paragraph of the report. Always plain, collapsed, at most MAX_SUMMARY_CHARS long.
extract_restart_request ¶
extract_restart_request(text: str) -> str | None
The subagent's RESTART_REQUIRED: reason, or None when it did not ask for one.
A restart takes Keryx off the air and kills the phone call, so this only ever reads an explicit line. Anything that merely looks like one — the words in a report, a changed checkout — is not it.