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

# Duckie as an External Subagent

> Call a focused Duckie agent from a customer-owned orchestration agent

Use Duckie as an external subagent when a customer-owned [orchestration agent](/concepts/routing-and-orchestration-patterns) should keep ownership of the overall workflow, but Duckie should handle a focused support task such as searching [knowledge](/knowledge/overview), summarizing context, classifying a request, or drafting a customer-safe answer.

This pattern is intentionally small: the customer's agent sends Duckie a task, Duckie runs a specialized agent, and Duckie sends the result back to the customer's system.

## Example Flow

```mermaid theme={null}
sequenceDiagram
  participant Orchestrator as Customer-owned orchestration agent
  participant Webhook as Duckie custom webhook
  participant Agent as Duckie search agent
  participant Knowledge as Duckie knowledge and tools
  participant Callback as Orchestrator callback API

  Orchestrator->>Webhook: POST task payload
  Webhook->>Agent: Start Duckie run
  Agent->>Knowledge: Search docs and call allowed tools
  Agent->>Callback: POST structured result
  Callback->>Orchestrator: Continue orchestration
```

[Custom webhook deployments](/deployments/custom-webhooks) accept the request and process it asynchronously. If the orchestrator needs the result, have the Duckie agent call a [custom tool](/tools/custom-tools) configured with a fixed callback API and a correlation ID rather than expecting the webhook response to include the final answer.

## When to Use This Pattern

Use Duckie as an external subagent when:

* You already have a primary [orchestration agent](/concepts/routing-and-orchestration-patterns) outside Duckie.
* Duckie should own a narrow support capability, not the whole customer journey. For the Duckie-native version of this pattern, see [Sub-Agents](/agents/sub-agents).
* The task benefits from Duckie [knowledge search](/knowledge/overview), [runbooks](/runbooks/overview), [guidelines](/guidelines/overview), [guardrails](/guardrails/overview), or [support tools](/tools/duckie-tools).
* Your orchestrator can continue after receiving an async callback from Duckie.

Good first tasks include:

* Search internal support docs and return a sourced answer.
* Classify a customer request into your support taxonomy.
* Summarize a ticket, conversation, or account record.
* Draft a customer-facing response for the orchestrator to review or send.
* Check policy eligibility and return a recommendation.

## What to Build

| Component                                                     | Purpose                                                            |
| ------------------------------------------------------------- | ------------------------------------------------------------------ |
| **Customer-owned orchestration agent**                        | Owns the parent workflow and decides when Duckie should be called. |
| **[Custom webhook deployment](/deployments/custom-webhooks)** | Receives the task payload and starts the Duckie agent.             |
| **[Focused Duckie agent](/agents/autonomous-agents)**         | Performs one narrow task, such as search or classification.        |
| **[Custom callback tool](/tools/custom-tools)**               | Sends the final result back to your orchestrator API.              |
| **Correlation ID**                                            | Connects the Duckie result to the parent orchestration task.       |

## Request Shape

Send the task to a Duckie [custom webhook](/deployments/custom-webhooks) as JSON.

```json theme={null}
{
  "event": {
    "id": "evt_123",
    "type": "subagent.search.requested"
  },
  "task": {
    "id": "task_456",
    "type": "knowledge_search",
    "question": "What is our refund policy for annual plans?"
  },
  "context": {
    "customer_id": "cus_789",
    "plan": "enterprise",
    "region": "us"
  }
}
```

Map the payload into:

| Duckie field     | Example mapping                                                                                                                          |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **Event ID**     | `$.event.id`                                                                                                                             |
| **Ticket ID**    | `$.task.id`                                                                                                                              |
| **Ticket Title** | `Duckie subagent task {{task.id}}`                                                                                                       |
| **Message Body** | `{{task.question}}`                                                                                                                      |
| **Run Metadata** | `task_id: $.task.id`, `task_type: $.task.type`, `customer_id: $.context.customer_id`, `plan: $.context.plan`, `region: $.context.region` |

Keep the webhook payload focused. Do not include secrets, credentials, API keys, or unnecessary sensitive data.

## Agent Setup

Create an [autonomous agent](/agents/autonomous-agents) with a narrow name and description, such as **External Knowledge Search Agent**.

Example instructions:

```text theme={null}
You are a focused research subagent for an external orchestration system.

Answer only the task provided in the current run. Search the available Duckie knowledge before answering. Use tools only when they are directly needed for the task.

Return a concise, structured result to the calling system by using the Send Subagent Result tool. Include the correlation ID from run metadata, the answer, relevant sources, confidence, and any caveats.

Do not send a customer-visible response unless explicitly instructed. If the task cannot be completed safely or confidently, return a low-confidence result with the missing information.
```

Give this agent access only to the [knowledge](/knowledge/overview), [runbooks](/runbooks/overview), [guidelines](/guidelines/overview), [guardrails](/guardrails/overview), and [tools](/tools/overview) required for the subtask. For a search agent, that usually means Duckie knowledge search and the callback custom tool.

## Callback Tool

Create a [custom tool](/tools/custom-tools) that posts the result back to your orchestrator API.

```text theme={null}
POST https://orchestrator.example.com/api/duckie/subagent-results
```

Example body parameters:

| Parameter        | Source                                                                          |
| ---------------- | ------------------------------------------------------------------------------- |
| `correlation_id` | Fixed value from `{{context.task_id}}` or another run metadata field            |
| `status`         | AI-generated enum-style string, such as `complete`, `needs_review`, or `failed` |
| `answer`         | AI-generated result text                                                        |
| `sources`        | AI-generated array of source references                                         |
| `confidence`     | AI-generated string, such as `high`, `medium`, or `low`                         |
| `notes`          | AI-generated caveats or missing information                                     |

Use a fixed callback endpoint. Pass task IDs, customer IDs, or routing keys as parameters instead of letting the agent choose a destination URL.

## Result Shape

The callback response to your orchestrator can look like this:

```json theme={null}
{
  "correlation_id": "task_456",
  "status": "complete",
  "answer": "Annual plans are refundable within 30 days if the account has not exceeded the usage threshold.",
  "sources": [
    {
      "title": "Refund Policy",
      "url": "https://example.com/refund-policy"
    }
  ],
  "confidence": "high",
  "notes": "The policy has an enterprise exception; confirm account-specific terms before issuing a refund."
}
```

Your orchestrator can then decide whether to continue the workflow, ask Duckie another focused task, send a customer response, or route to a human.

## Testing

1. Create the webhook deployment in [**Testing** mode](/deployments/deployment-modes).
2. Send a representative task payload with a correlation ID.
3. Open [**Analyze > Runs**](/analytics/runs) and verify the message, metadata, searched knowledge, and tool calls.
4. Confirm your callback API receives one result for the task.
5. Test missing context, low-confidence answers, and callback failures before switching the deployment to [**Live**](/deployments/deployment-modes).

## Related Docs

<CardGroup cols={2}>
  <Card title="Custom Webhooks" icon="plug" href="/deployments/custom-webhooks">
    Trigger Duckie from your orchestration system.
  </Card>

  <Card title="Custom Tools" icon="wrench" href="/tools/custom-tools">
    Send the subagent result back to your API.
  </Card>

  <Card title="Autonomous Agents" icon="wand-magic-sparkles" href="/agents/autonomous-agents">
    Configure the focused Duckie agent.
  </Card>

  <Card title="Run History" icon="clock-rotate-left" href="/analytics/runs">
    Review the Duckie run, tool calls, and callback result.
  </Card>

  <Card title="Designing Agent Systems" icon="diagram-project" href="/examples/designing-agent-systems">
    Place this pattern inside a larger agent architecture.
  </Card>

  <Card title="Single Agents vs Sub-Agents" icon="diagram-project" href="/concepts/single-agents-vs-sub-agents">
    Compare internal delegation with external orchestration.
  </Card>
</CardGroup>
