Pausing and Resuming Agents Through API Calls

Introduction: Adding Lifecycle Control to Agent APIs

In the previous lesson, you implemented database persistence and progress callbacks that save the agent's state after each step. This allows clients to monitor progress in real time, but they still have no control over the agent once it starts running. Now it's time to complete Factor 6 — Launch / Pause / Resume with simple APIs. You already have the launch endpoint from lesson one and the durable persistence layer from lesson two; in this lesson, you add the pause and resume endpoints that give users the power to stop expensive computations temporarily or correct mistakes without losing progress. You will implement these endpoints using a cooperative pause mechanism that lets agents stop gracefully between steps.

How the Pause Mechanism Works

Unlike forcefully terminating a thread or process, a cooperative pause lets the agent finish its current step before stopping. This approach works by having the pause endpoint change the database status field to "paused" and requiring the agent's progress callback to check for this status change after each step completes.

When the callback detects that the status has been changed externally, it updates the local state object to reflect the pause, causing the agent's main loop to exit on its next iteration. The advantage of this design is that it never interrupts the agent mid-step, ensuring the agent's state remains consistent and valid, with all fields properly synchronized. This is exactly what Factor 6 calls for: the agent can checkpoint, wait, and resume reliably across time.

Modifying the Progress Callback to Detect Pause Requests

As a reminder from the previous lesson, the progress callback is called after each agent step to save the current state to the database. To support pause detection, you need to modify this callback to check whether the database status was changed to "paused" by an external request:

def _create_progress_callback(state_id: str):
    """Create a progress callback function that saves state after each step"""
    def save_progress(state: State):
        with get_db_session() as session:
            db_state = session.query(StateModel).filter(StateModel.id == state_id).first()
            if db_state:
                # Check if status was changed to "paused" externally (via pause endpoint)
                if db_state.status == "paused":
                    # Update local state to paused so agent loop will exit
                    state.status = "paused"
                    # Don't overwrite the paused status - just save other fields
                    db_state.steps = state.steps
                    db_state.context = state.context
                    db_state.pending_tool_calls = state.pending_tool_calls
                    db_state.error = state.error
                    db_state.final_answer = state.final_answer
                else:
                    # Normal save - update all fields including status
                    db_state.steps = state.steps
                    db_state.status = state.status
                    db_state.context = state.context
                    db_state.pending_tool_calls = state.pending_tool_calls
                    db_state.error = state.error
                    db_state.final_answer = state.final_answer
    return save_progress

The modified callback first queries the database to load the current record and then checks whether db_state.status equals "paused". If it does, the callback recognizes that an external request changed the status and updates the local state.status to "paused" as well. This status change causes the agent's main loop condition, while state.status == "running", to evaluate to False on the next iteration, ending the workflow.

The callback then saves all other fields without overwriting the "paused" status, preserving the pause signal. In the normal case where no pause was requested, the callback updates all fields, including status, maintaining the previous behavior you implemented in the last lesson.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal