Agent Runtime ============= How **ThreadRunner** turns an Agent configuration into a LangGraph invoke that Agency can audit and resume. What ThreadRunner builds ------------------------ ``agency.agent.ThreadRunner`` compiles a graph with: * **Agent** — instructions, tool list (``get_tools()``), default model * **Model** — resolved via ``resolve_model`` (optional override, else ``agent.model``) → ``build_chat_model`` * **Tools** — BaseTool callables from the Tool catalog * **CheckpointSaver** — Django-backed LangGraph checkpointer * **RunMiddleware** — run lifecycle / telemetry hooks for Monitor * **Run** + config — ``thread_id``, ``run_id``, ``checkpoint_ns`` Deep agents use ``create_deep_agent`` when ``ThreadRunner(deep=True)`` or ``Agent.deep`` is set; otherwise ``create_agent``. Deepagents' in-process ``task`` subagents block the Celery worker — product handoffs use a specialist Agent + Mission and ``wait_for_execution`` / ``commission_display_view``. ``run()`` flow -------------- :: ThreadRunner.run(agent, input) │ ├─ ensure Thread ├─ create Run ├─ messages = [system instructions?, user input] └─ invoke(...) ├─ create_graph(agent, run) ├─ run status → STARTING / RUNNING (middleware) ├─ graph.invoke(input, config={thread_id, run_id, …}) ├─ CheckpointSaver persists graph state └─ outcomes ├─ SUCCESS path (middleware / complete output) ├─ INTERRUPTED → check_interrupt → Interruption row └─ ERROR → Run.error + re-raise ``resume()`` flow ----------------- :: ThreadRunner.resume(interruption) │ ├─ thread = interruption.get_thread() # same timeline ├─ create Run (status RESUMING) └─ invoke(Command(resume=interruption.answer), config={same thread_id, new run_id}) The previous interrupted Run is left as-is. Continuation state comes from the persisted checkpoint associated with the interruption, not from an in-memory worker. Who calls ThreadRunner ---------------------- * ``Agent.execute`` — used by Celery ``start_mission`` * ``ThreadRunner().resume`` — used by Celery ``resume_mission`` * ``ThreadRunner().continue_turn`` — Celery ``continue_mission`` (Mission Control) * ``agency.thread.service.send_message`` — Celery ``continue_personal_thread`` (secretary conversation; ``execution_id`` is NULL) Smoke path ``Agent.test`` builds a graph **without** ThreadRunner / CheckpointSaver / Run records — not the product runtime. See also: :doc:`execution`, :doc:`../../tutorials/human-in-the-loop`, module reference :doc:`../../framework/agency/runtime`.