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

# Server tools

> Run typed, validated capabilities inside the agent server.

Use `@tool` when the capability should execute inside the agent server.

When only part of a tool needs isolated Python execution, call an assigned [Sandbox](/docs/harnest/build/sandboxing) through `context.sandboxes["<name>"].execute(code)` or async `aexecute(code)`. The model calls your business tool, not the sandbox directly; your tool validates inputs and chooses which result to return. The surrounding tool code still runs in the agent server.

```python tools/lookup_order.py theme={null}
from harnest.models.orders import OrderStatus
from harnest.agent import tool


@tool(output_schema=OrderStatus)
def lookup_order(order_id: str):
    """Load one order status."""

    return {"order_id": order_id, "status": "processing"}
```

## Tool properties

| Property           | Rule                                                                                                          |
| ------------------ | ------------------------------------------------------------------------------------------------------------- |
| File               | `tools/lookup_order.py`                                                                                       |
| Export             | `lookup_order`                                                                                                |
| Description        | Docstring or `@tool(description="...")`; distinguish similar parameters explicitly                            |
| Output validation  | Pydantic return annotation or `output_schema`                                                                 |
| Runtime permission | `@tool(permission="tickets.read")`; required when the tool must be available under an Agent Runtime Principal |
| Unit testing       | Call the decorated function directly                                                                          |

Arguments and results must be structured. Convert unsupported custom objects to a Pydantic model or mapping at the tool boundary.

Expose supported filters, pagination, and ordering as typed parameters or separate typed tools. Do not ask the model to invent undeclared options. Managed ADK and LangGraph reject unknown argument names before native framework coercion and return repair guidance without echoing argument values.

## Runtime access

| Need                  | Use                                      |
| --------------------- | ---------------------------------------- |
| Application resource  | `context.resource("name")`               |
| Current user          | `context.user_id`                        |
| Current session       | `context.session_id`                     |
| Downstream credential | `await context.credentials.resolve(...)` |

Credentials are private invocation capabilities. Do not expose them as model-generated arguments or ordinary context resources.

Use `permission=` when trusted application code must select whether the tool is available for one invocation. An active principal denies an untagged tool. See [Agent Runtime Principals](/docs/harnest/runtime/agent-runtime-principals).

## Wait durably

Use an async durable tool when queued or external work must survive a request ending or a replica stopping:

```python tools/request_report.py theme={null}
from harnest.lib.report_tasks import build_report
from harnest.agent import tool


@tool(durable=True)
async def request_report(account_id: str):
    handle = await build_report.defer(account_id=account_id)
    return await handle.result()
```

`durable=True` resumes framework execution; it does not restore a Python frame. See [Durable execution](/docs/harnest/runtime/durable-execution).

## Add approval

<Tabs>
  <Tab title="Every call">
    ```python theme={null}
    from harnest.agent.approval import require_human_approval


    @tool
    @require_human_approval(message="Approve deleting {customer_id}?")
    def delete_customer(customer_id: str):
        return database.delete_customer(customer_id)
    ```
  </Tab>

  <Tab title="After evaluation">
    Protect only the sensitive block with `request_human_approval(...)`.

    <Card title="Dynamic human approval" icon="user-check" href="/docs/harnest/build/agent-tools/human-approvals">
      Evaluate risk before deciding whether the operation needs permission.
    </Card>
  </Tab>
</Tabs>
