Skip to content

Human-in-the-Loop

Deep Agents' interrupt() works out of the box with deepagent-temporal. The Workflow pauses with zero resource consumption and resumes when you send a Signal.

Starting a workflow with HITL

# Start the agent (non-blocking)
handle = await temporal_agent.astart(
    {"messages": [HumanMessage(content="Refactor auth module")]},
    config={"configurable": {"thread_id": "task-456"}},
)

Checking for interrupts

state = await temporal_agent.get_state(
    {"configurable": {"thread_id": "task-456"}}
)

if state["status"] == "interrupted":
    print("Pending approval:", state["interrupts"])

Resuming

await temporal_agent.resume(
    {"configurable": {"thread_id": "task-456"}},
    "approved",
)

Complete example

import asyncio
from deepagent_temporal import TemporalDeepAgent

async def run_with_approval():
    # Start agent
    handle = await temporal_agent.astart(
        {"messages": [HumanMessage(content="Deploy to production")]},
        config={"configurable": {"thread_id": "deploy-1"}},
    )

    # Poll for interrupt (in practice, use a webhook or UI)
    while True:
        state = await temporal_agent.get_state(
            {"configurable": {"thread_id": "deploy-1"}}
        )

        if state["status"] == "interrupted":
            print("Agent needs approval:", state["interrupts"])
            approval = input("Approve? (y/n): ")
            await temporal_agent.resume(
                {"configurable": {"thread_id": "deploy-1"}},
                "approved" if approval == "y" else "rejected",
            )

        if state["status"] == "completed":
            break

        await asyncio.sleep(1)

    result = await handle.result()
    print("Final result:", result)

Why this matters for agents

In vanilla Deep Agents, interrupt() blocks a running process. With Temporal:

  • No compute wasted — the Worker is free to handle other Workflows while waiting
  • Survives restarts — if the Worker restarts, the paused state is preserved in Temporal's event history
  • No timeout — the Workflow can wait days or weeks for human input
  • Queryable from anywhere — check interrupt status from any process, API, or UI