> ## Documentation Index
> Fetch the complete documentation index at: https://docs.goguava.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# on_task_complete()

> React when the agent completes a task

<Tabs>
  <Tab title="Python">
    `on_task_complete` is called when a [Task](/sdk-reference/tasks) previously set with `call.set_task()` is completed by the agent. Use it to persist collected data, trigger downstream workflows, or move the call to the next stage.
  </Tab>

  <Tab title="TypeScript">
    `onTaskComplete` is called when a [Task](/sdk-reference/tasks) previously set with `call.setTask()` is completed by the agent. Use it to persist collected data, trigger downstream workflows, or move the call to the next stage.
  </Tab>
</Tabs>

## Signature

There are two forms:

<Tabs>
  <Tab title="Python">
    ```python signature theme={null}
    # Per-task form (recommended)
    @agent.on_task_complete("task_name")
    def handler(call: guava.Call) -> None:
        ...

    # Generic form — fires for all tasks
    @agent.on_task_complete
    def handler(call: guava.Call, task_id: str) -> None:
        ...
    ```

    * **Per-task form** (recommended): `@agent.on_task_complete("task_name")` binds the handler to a specific `task_id`. The handler receives only the `Call` object.
    * **Generic form**: `@agent.on_task_complete` (bare decorator) fires for every completed task. The handler receives the `Call` object and the `task_id` string, letting you dispatch on it manually.

    <Warning>
      You cannot mix both forms on the same agent — using per-task handlers alongside a generic handler raises a `TypeError`.
    </Warning>

    * `on_task_complete` fires once all checklist items are resolved and the agent has signaled completion.
    * Use [`call.get_field()`](/sdk-reference/get-field) inside the handler to read values collected during the task.
    * The call is still live when this handler runs — you can issue commands such as `call.set_task()`, `call.hangup()`, or `call.transfer()`.
  </Tab>

  <Tab title="TypeScript">
    ```typescript signature theme={null}
    // Per-task form (recommended)
    agent.onTaskComplete("task_name", async (call: guava.Call) => void);

    // Generic form — fires for all tasks
    agent.onTaskComplete(async (call: guava.Call, taskId: string) => void);
    ```

    * **Per-task form** (recommended): `agent.onTaskComplete("task_name", handler)` binds the handler to a specific `taskId`. The handler receives only the `Call` object.
    * **Generic form**: `agent.onTaskComplete(handler)` fires for every completed task. The handler receives the `Call` object and the `taskId` string, letting you dispatch on it manually.

    <Warning>
      You cannot mix both forms on the same agent — using per-task handlers alongside a generic handler throws an `Error`.
    </Warning>

    * `onTaskComplete` fires once all checklist items are resolved and the agent has signaled completion.
    * Use [`call.getField()`](/sdk-reference/get-field) inside the handler to read values collected during the task.
    * The call is still live when this handler runs — you can issue commands such as `call.setTask()`, `call.hangup()`, or `call.transfer()`.
  </Tab>
</Tabs>

## Example

<Tabs>
  <Tab title="Python">
    ```python waitlist_controller.py theme={null}
    import logging
    import guava
    from guava import Agent

    logger = logging.getLogger(__name__)

    agent = Agent(
        organization="Thai Palace",
        purpose="Add callers to the waitlist",
    )

    @agent.on_call_start
    def on_call_start(call: guava.Call):
        call.set_task(
            "waitlist",
            objective="Add the caller to the waitlist.",
            checklist=[
                guava.Field(key="caller_name", field_type="text", description="Name for the waitlist"),
                guava.Field(key="party_size", field_type="integer", description="Number of people"),
                guava.Field(key="phone_number", field_type="text", description="Phone number to text when ready"),
                "Read the phone number back to the caller to confirm.",
            ],
        )

    @agent.on_task_complete("waitlist")
    def on_waitlist_done(call: guava.Call):
        name = call.get_field("caller_name")
        size = call.get_field("party_size")
        logger.info("Added %s, party of %d, to waitlist.", name, size)
        call.hangup("Thank the caller and let them know we'll text when their table is ready.")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript waitlist_controller.ts theme={null}
    import * as guava from "@guava-ai/guava-sdk";

    const agent = new guava.Agent({
      organization: "Thai Palace",
      purpose: "Add callers to the waitlist",
    });

    agent.onCallStart(async (call) => {
      await call.setTask({
        taskId: "waitlist",
        objective: "Add the caller to the waitlist.",
        checklist: [
          guava.Field({ key: "caller_name", fieldType: "text", description: "Name for the waitlist" }),
          guava.Field({ key: "party_size", fieldType: "integer", description: "Number of people" }),
          guava.Field({ key: "phone_number", fieldType: "text", description: "Phone number to text when ready" }),
          "Read the phone number back to the caller to confirm.",
        ],
      });
    });

    agent.onTaskComplete("waitlist", async (call) => {
      const name = await call.getField("caller_name");
      const size = await call.getField("party_size");
      console.log(`Added ${name}, party of ${size}, to waitlist.`);
      await call.hangup("Thank the caller and let them know we'll text when their table is ready.");
    });
    ```
  </Tab>
</Tabs>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.