Skip to content

Advanced Guide: Human-in-the-Loop

For many critical tasks, you need to pause an agent's execution and ask for human approval. The StatefulOrchestrator supports this with a special __interrupt__ node.

Example: Agent Seeking Approval

This is a complete, runnable script demonstrating a human-in-the-loop workflow.

from safeagent import *

# --- Setup ---
gov = GovernanceManager()
llm = LLMClient(api_key=Config().api_key)
def send_email(body: str): 
    print("--- EMAIL SENT ---")
    print(body)

# --- Agent Nodes ---
def draft_email(state: dict) -> dict:
    prompt = f"Draft a polite email about: {state['topic']}"
    response = llm.generate(prompt, max_tokens=100)
    return {"draft": response['text']}

def get_human_approval(state: dict) -> str:
    return "__interrupt__"

# --- Build and Run ---
agent = StatefulOrchestrator(entry_node="draft_email")
agent.add_node("draft_email", draft_email)
agent.add_node("send_final_email", lambda state: send_email(state['final_draft']))
agent.add_conditional_edge("draft_email", get_human_approval)
agent.add_edge("send_final_email", "__end__")

gov.start_new_run() 
initial_state = {"topic": "team meeting moved to 3 PM"}
status, paused_state = agent.run(initial_state)

print(f"\n--- AGENT PAUSED --- DRAFT FOR APPROVAL:\n{paused_state['draft']}")

if status == "paused":
    feedback = input("\nType 'approve' or provide edits: ")
    human_input = {"final_draft": paused_state['draft'] if "approve" in feedback.lower() else feedback}
    paused_state['__next_node__'] = 'send_final_email'

    status, final_state = agent.resume(paused_state, human_input)
    print(f"\n--- AGENT COMPLETED --- Final Status: {status}")