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

# Decorators

> Reference for the @agent, @chain, and @tool decorators that auto-instrument your code.

Three decorators cover the vast majority of instrumentation needs. Each captures inputs and outputs, measures duration, and emits `*_start` and `*_end` events to Observatory.

***

## `@agent`

The top-level decorator. Wrap the function that handles one user request.

```python theme={"system"}
from flowxobservatory import agent

@agent("claims-approval")
def run(ctx, payload):
    # business logic
    return result
```

### Parameters

<ParamField path="name" type="string" required>
  The agent identifier. Shows up in the **Agent** column on LLM Calls, in Risk Dashboard, and in ROI baselines. Use kebab-case.
</ParamField>

<ParamField path="user_id" type="string">
  Identifier of the user this run belongs to. Surfaces in filters and Threads grouping.
</ParamField>

<ParamField path="user_props" type="dict">
  Arbitrary user properties attached to the run (e.g. `{"plan": "enterprise"}`).
</ParamField>

<ParamField path="tags" type="list[str]">
  Tags attached to every run of this agent (e.g. `["claims", "prod"]`). Used for filtering in LLM Calls and analytics.
</ParamField>

***

## `@chain`

Use for sub-steps that aren't external work but are worth seeing in the trace.

```python theme={"system"}
from flowxobservatory import chain

@chain("extract-claim-data")
def extract(payload):
    return {"holder": payload["policy_id"], ...}
```

### Parameters

Same shape as `@agent`. The chain inherits the parent run's app and project context — you only need to name it.

<Tip>
  If you're using LangChain or LangGraph, the callback handler creates chain spans automatically. Use `@chain` for handwritten Python that lives between LangChain calls or for non-LangChain frameworks.
</Tip>

***

## `@tool`

Use for the leaf-level units of work — database queries, REST calls, file operations, computation.

```python theme={"system"}
from flowxobservatory import tool

@tool("lookup_policy_holder")
def lookup_policy_holder(policy_id):
    return db.fetch(policy_id)
```

### Parameters

Same signature as `@agent` — `name`, `user_id`, `user_props`, `tags`.

***

## Async functions

All three decorators detect `async def` and wrap it natively. No different syntax.

```python theme={"system"}
@agent("claims-approval")
async def run(ctx, payload):
    data = await extract(payload)
    return await decide(data)
```

***

## Error handling

If the wrapped function raises, the SDK:

1. Emits an `*_end` event with `status=error` and the exception's class and message.
2. Re-raises the exception unchanged.

Your error handling does not need to change. Observatory captures the error context; your `try/except` still runs.

***

## Class-based instrumentation

The decorators also work on methods. Use `@agent` on the entry method of a class:

```python theme={"system"}
class ClaimsAgent:
    @agent("claims-approval")
    def run(self, ctx, payload):
        ...
```

`self` is excluded from captured inputs automatically.

***

## When NOT to use a decorator

| Situation                                           | Better choice                                      |
| --------------------------------------------------- | -------------------------------------------------- |
| You want to attach a custom event (`saved`, `chat`) | Call `track_event()` directly.                     |
| The function runs millions of times per request     | Decorate the parent, not the leaf.                 |
| You only want to record success metrics             | Use the analytics API on the recorded run instead. |

***

## Related resources

<CardGroup cols={2}>
  <Card title="Event reporting" icon="paper-plane" href="./event-reporting">
    Custom events and the wire protocol.
  </Card>

  <Card title="SDK overview" icon="code" href="./overview">
    Install and configuration.
  </Card>
</CardGroup>
