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

# report_external_task

> Record an externally-executed run so it appears in task history.

`Backend.areport_external_task` logs a task that was executed outside the xpander.ai runtime (for example, in a queue worker, a Lambda, or a different process) so it shows up in the same task history, metrics, and observability views as platform-managed tasks.

Use this when you've called an LLM yourself (outside of an `@on_task` handler) but still want the run to count toward agent metrics and appear in the dashboard.

```python theme={"dark"}
from xpander_sdk import Backend, Tokens

backend = Backend()

reported = await backend.areport_external_task(
    agent_id="agent-123",
    id="ext-job-9921",
    input="Summarize Q4 earnings",
    result="Q4 revenue grew 22% YoY, driven by ...",
    tokens=Tokens(prompt_tokens=2_140, completion_tokens=380),
    duration=4.7,
    used_tools=["web_search", "fetch_pdf"],
    is_success=True,
)
print(reported.id, reported.status)
```

### Parameters

| Parameter       | Type            | Required | Default                    | Description                                                                        |
| --------------- | --------------- | -------- | -------------------------- | ---------------------------------------------------------------------------------- |
| `agent_id`      | `str`           | No¹      | `XPANDER_AGENT_ID` env var | Agent the run is associated with. Falls back to `agent.id` if `agent` is provided. |
| `agent`         | `Agent`         | No¹      | `None`                     | Pre-loaded `Agent` instance. Takes precedence over `agent_id`.                     |
| `id`            | `str`           | No       | `None`                     | External task identifier. Re-using the same ID updates the existing record.        |
| `input`         | `str`           | No       | `None`                     | Input prompt for the run.                                                          |
| `llm_response`  | `Any`           | No       | `None`                     | The raw LLM response object (provider-specific). Stored verbatim for debugging.    |
| `tokens`        | `Tokens`        | No       | `None`                     | Token usage. Used by metrics.                                                      |
| `is_success`    | `bool`          | No       | `True`                     | Whether the run completed successfully. Sets task status accordingly.              |
| `result`        | `str`           | No       | `None`                     | Final result string.                                                               |
| `duration`      | `float`         | No       | `0`                        | Wall-clock duration in seconds.                                                    |
| `used_tools`    | `list[str]`     | No       | `None`                     | Names of tools the run called.                                                     |
| `configuration` | `Configuration` | No       | Module's config            | Override SDK configuration for this call.                                          |

¹ Either `agent_id` or `agent` must resolve. The method also reads `XPANDER_AGENT_ID` as a final fallback.

### Returns `Task`

The platform-side `Task` record after persistence. Re-using `id` returns the updated record; new `id`s create a fresh task.

## Examples

### Idempotent updates

Pass the same `id` to update an in-progress task as it makes progress:

```python theme={"dark"}
# Mark started
await backend.areport_external_task(
    agent_id="agent-123",
    id="job-7842",
    input="Long-running data extraction",
    is_success=True,
    result=None,
    duration=0,
)

# ... do the work ...

# Mark completed with final tokens
await backend.areport_external_task(
    agent_id="agent-123",
    id="job-7842",
    input="Long-running data extraction",
    result="Extracted 412 rows",
    tokens=Tokens(prompt_tokens=18_400, completion_tokens=2_100),
    duration=37.6,
    is_success=True,
    used_tools=["s3_read", "snowflake_query"],
)
```

### Using a pre-loaded agent

```python theme={"dark"}
agent = await agents.aget("agent-123")

await backend.areport_external_task(
    agent=agent,
    id="ext-2025-04-25-001",
    input="Daily summary",
    result="...",
    is_success=True,
)
```

### Reporting a failure

```python theme={"dark"}
try:
    result = run_llm_locally(prompt)
except Exception as e:
    await backend.areport_external_task(
        agent_id="agent-123",
        id="job-failed-001",
        input=prompt,
        result=str(e),
        is_success=False,
    )
    raise
```

`is_success=False` marks the task as failed in the dashboard.

## Sync version

```python theme={"dark"}
backend.report_external_task(
    agent_id="agent-123",
    id="ext-001",
    input="...",
    result="...",
)
```

Same signature; blocks until the report is persisted.
