> ## Documentation Index
> Fetch the complete documentation index at: https://shinydapps-bd9fa40b.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent-to-Agent Delegation

> Let an orchestrator pay once and share the credential with sub-agents.

## Concept

An L402 token (`macaroon:preimage`) is a portable string — once paid, it can be passed to any sub-agent that needs access to the same resource. The orchestrator holds the wallet; sub-agents only receive a token.

```
Orchestrator (has wallet)
   │
   ├── pays invoice → receives token (macaroon:preimage)
   │
   ├── passes token string to SubAgent A
   └── passes token string to SubAgent B

SubAgent A — calls /api/data with token  ✓  (no wallet needed)
SubAgent B — calls /api/data with token  ✓  (no wallet needed)
```

<Note>
  Tokens expire after 1 hour. Each preimage can only be used once per server (replay protection). For parallel sub-agents hitting the same endpoint, each needs its own payment.
</Note>

## When to share a token vs. pay independently

There are two delegation patterns, each with different trade-offs:

**Token sharing** works when sub-agents access the **same endpoint sequentially**. The orchestrator pays once, extracts the `Authorization` header value, and passes it as a string. Sub-agents call the endpoint with that header directly — no wallet required. This minimizes cost (one payment) but is **not safe for concurrent access** — only one agent can hold a given preimage, and servers reject replays.

**Independent payment** (each sub-agent has its own `L402Client` sharing the orchestrator's wallet) works for **parallel or concurrent access**. Each agent pays its own invoice and caches its own token. This costs more sats but is simpler to reason about and safe at any concurrency level.

**Rule of thumb:** If your sub-agents fan out in parallel, give each its own `L402Client`. If they run sequentially and hit the same endpoint, share the token string.

## Security considerations

* **Never pass wallet credentials to sub-agents.** Pass only the token string (`L402 <macaroon>:<preimage>`). A token can call one endpoint for up to one hour — a private key can drain a wallet.
* **Tokens are single-use per server.** After the first accepted request, the server records the preimage hash. A second request with the same preimage returns 402. This prevents replay attacks but means you cannot share one token across two concurrent sub-agents hitting the same server.
* **Budget control is at the wallet level.** Set `budgetSats` on the orchestrator's `L402Client` to cap total spend across all sub-agents sharing that wallet. See [Budget Control](/agent/budget).

## TypeScript — orchestrator pays, sub-agent uses token

```typescript theme={null}
import { L402Client, BlinkWallet } from "l402-kit";

// Orchestrator: has wallet, pays invoice
const wallet = new BlinkWallet(process.env.BLINK_API_KEY!, process.env.BLINK_WALLET_ID!);
const orchestrator = new L402Client({ wallet, budgetSats: 5000 });

// Fetch triggers payment; token is cached inside orchestrator
const res = await orchestrator.fetch("https://api.example.com/data");
const data = await res.json();

// Build the delegation header from the macaroon + preimage the Lightning Network returned.
// In practice, retrieve these from the payment result or the client's token cache.
// Format is always: "L402 <base64-macaroon>:<hex-preimage>"
const tokenHeader = `L402 ${macaroon}:${preimage}`; // substitute values from payment result

// Sub-agent: no wallet, passes the header directly
const subRes = await fetch("https://api.example.com/data", {
  headers: { Authorization: tokenHeader },
});
```

## Python — orchestrator pays, sub-agent uses token

```python theme={null}
from l402kit import L402Client
from l402kit.wallets.blink import BlinkWallet

# Orchestrator pays
wallet = BlinkWallet(api_key=os.environ["BLINK_API_KEY"])
orchestrator = L402Client(wallet=wallet, budget_sats=5000)

async with orchestrator:
    response = await orchestrator.fetch("https://api.example.com/data")

# Sub-agents: pass the Authorization header directly
# Authorization: L402 <macaroon>:<preimage>
```

## Multi-agent pattern: one payment, parallel reads

If multiple sub-agents need the **same resource concurrently**, the cleanest pattern is for each sub-agent to pay independently using its own `L402Client` with a shared wallet:

```typescript theme={null}
import { L402Client, BlinkWallet } from "l402-kit";

const wallet = new BlinkWallet(process.env.BLINK_API_KEY!, process.env.BLINK_WALLET_ID!);

// Each sub-agent gets its own L402Client — independent payment + token cache
const agents = Array.from({ length: 3 }, () => new L402Client({ wallet }));

const results = await Promise.all(
  agents.map((agent) => agent.fetch("https://api.example.com/data"))
);
```

## Security properties

| Property         | How it works today                                    |
| ---------------- | ----------------------------------------------------- |
| Wallet isolation | Sub-agents receive a token string, never private keys |
| Time-bound       | Macaroons expire after 1 hour                         |
| Replay-safe      | Each preimage can only be accepted once by the server |
| Budget control   | Set `budgetSats` on the orchestrator `L402Client`     |

## Coming in a future version

Full macaroon caveat delegation (endpoint scoping, single-use tokens, max-use limits) is planned. Track progress on [GitHub](https://github.com/ShinyDapps/l402-kit).

See [Budget Control](/agent/budget) for session-level spending limits.
