Skip to content

Tools and approvals

The @tool decorator converts a typed Python function into a validated provider schema and an async execution boundary.

from agentmuru import tool

@tool(
    permission="orders.refund",
    approval="required",
    risk="high",
    side_effects=True,
    sensitive_fields={"payment_token"},
)
def refund_order(order_id: str, payment_token: str) -> dict[str, str]:
    """Refund one approved order."""
    return {"order_id": order_id, "status": "refunded"}

Validation

The function signature becomes JSON Schema. Required parameters stay required, defaults are preserved, unknown arguments fail, and values are coerced against supported Python type hints. Sync handlers run in a worker thread. Async handlers run in the event loop.

Each tool also controls timeout, retries, risk, side-effect classification, permission, and fields that must be redacted from public events.

Permission comes first

Declaring permission="orders.refund" does not grant it. The agent must also include that string in Agent.permissions. A missing grant ends the run with permission_denied before the handler executes.

Approval modes

Mode Behavior
auto Policy decides from risk and side-effect metadata
required Runtime always creates an approval request before execution
never Runtime never pauses for human approval

An approval stores the tool name, public arguments, permission, risk, actor, reason, and final decision. Rejection and expiry do not execute the handler.

Safe event payloads

Sensitive fields become [REDACTED] before tool arguments enter public runtime events. The runtime persists the complete assistant tool call for provider continuity, while operator events expose only the redacted view.