# Delegated agents never exceed their parents

An agent working for another agent may use only what every agent above it may use. Start by logging what would be refused, then enforce it.

When an agent hands work to another agent (ask_agent, delegate, A2A, or a chain passed over MCP), the child's tool calls used to be decided on the child alone. An orchestrator that a policy forbade from a tool could reach it anyway by asking a child that had the tool.

Liyagent now checks every agent above the child in the delegation chain, on every tool the child is offered and every call it makes.

## What is checked

For each agent above the child:

- **Cedar** (always): the same server gate and `call_tool` decision the ancestor's own call would get. A `forbid` on the parent holds through all of its children, however deep.
- **Strict** (`strict: true`): also the ancestor's own tool list. A child may use only tools that its parent attaches. Built-in agents and names with no registry row have no tool list, so they are held to Cedar only.

Only the chain this instance recorded counts. A chain that a caller merely claims in a header or message never narrows or widens anything here.

## Modes

```http
GET /api/delegation/attenuation
PUT /api/delegation/attenuation
{"mode": "log", "strict": false}
```

| Mode | What happens |
| --- | --- |
| `log` (default) | Calls go through exactly as before. What enforcement would refuse is written as `delegation.attenuation.would_deny`, once per chain, tool and reason every 10 minutes. |
| `enforce` | The tool is left out of the child's tool list. A call to it is refused with "… is working for orchestrator, and orchestrator may not call wiki/edit". Each refusal is written as `delegation.attenuation.denied`. |
| `off` | Nothing is checked. |

`log` is the default because many live set-ups depend on the opposite. For example, Liya routes requests to the HR and SAP agents, which hold tools Liya itself does not.

Before you switch to `enforce`, read the `would_deny` rows. Then either give the parent the permits it needs, or accept that those delegations will stop. Changing the setting needs `access.write` and is audited as `delegation.attenuation.settings`.
