Skip to content
94 changes: 94 additions & 0 deletions content/trading/swapping-api/agent-attribution.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: Agent Attribution (X-Agent-Info)
description: Send the optional X-Agent-Info header to attribute agent-driven Trading API traffic, and check x-agent-info-status to confirm it was recognized.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Frontmatter claims a response header that doesn't appear to exist. This description (and the "Confirming it was received" section below) documents an x-agent-info-status response header. Per the PR's own description, this header shipped in Uniswap/backend#11003, which was closed unmerged and superseded by #11941 (gateway parser only) — a git grep x-agent-info-status on backend main reportedly returns nothing. If that's accurate, this page documents a feature that was never shipped. Please confirm against the current backend implementation before merging (the PR author flagged this as "not ready to merge" for this exact reason).

---

The Uniswap API accepts an optional `X-Agent-Info` request header. Send it if an AI agent built or operates your integration. It lets us measure agent-driven traffic separately from human-driven traffic.

<Callout title="Optional, and never affects the request" type="info">

`X-Agent-Info` is purely for analytics. Humans and human-facing clients can ignore it entirely. Omitting it, sending it, or sending it incorrectly has no effect on your request. It never changes the response status, body, or any swap behavior.

</Callout>

## Sending the header

Send `X-Agent-Info` alongside your usual [authentication](/docs/trading/swapping-api/integration-guide#authentication) headers, with a JSON object value containing up to three fields:

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `decision_origin` | string | Yes | Must be exactly `autonomous` or `human_mediated` (case-sensitive). Any other value marks the header malformed. |
| `integration_name` | string | No | Name of your integration or agent, e.g. `my-trading-bot`. Up to 256 UTF-16 code units — JavaScript's `String#length`. |
| `version` | string | No | Version identifier for your integration. Up to 256 UTF-16 code units. |

Send only these three fields. Any other key is dropped rather than rejected, so an extra key never makes the header malformed.

`integration_name` and `version` are stored per request and queried later. Both must be stable strings that describe your software. Never send a user ID, wallet address, email address, session token, API key, or any value derived from an end user. On our side, a malformed header is never echoed back or logged, and only the three fields above ever reach our analytics.

```bash
# Fill in your own token addresses and amount. The header is evaluated either way.
curl -X POST https://trade-api.gateway.uniswap.org/v1/quote \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H 'X-Agent-Info: {"decision_origin":"autonomous","integration_name":"my-trading-bot","version":"1.4.0"}' \
-d '{"tokenIn":"0x...","tokenOut":"0x...","tokenInChainId":1,"tokenOutChainId":1,"type":"EXACT_INPUT","amount":"1000000","swapper":"0x...","slippageTolerance":0.5}'
```

## What makes a header malformed

A header is dropped (marked malformed) rather than rejected outright if any of the following hold. The request is handled exactly as if the header were absent — see [Confirming it was received](#confirming-it-was-received) below for how to tell the difference.

- The raw header value is larger than **1024 bytes**, measured on the raw value before parsing. JSON whitespace and `\u` escapes count toward the cap.
- The raw header value contains any byte outside printable US-ASCII (`0x20`–`0x7E`). This is checked first, before the JSON is parsed, because bytes above `0x7E` decode differently in different HTTP stacks. So a literal `é`, an emoji, or a curly quote in the header marks it malformed no matter how short the value is. Send non-ASCII as a JSON `\u` escape instead.
- The value isn't valid JSON, or is valid JSON that isn't a plain object (an array, string, number, boolean, or `null`).
- The request carried two or more `X-Agent-Info` header lines. They are joined with `", "`, which is almost never valid JSON. Set the header once rather than appending to it — some HTTP clients append by default.
- `decision_origin` is missing, or is anything other than exactly `autonomous` or `human_mediated`.
- `integration_name` or `version` is present but isn't a string, or is longer than 256 UTF-16 code units. That count is JavaScript's `String#length`, so an emoji or other astral character costs two units, not one.
- `integration_name` or `version` contains a disallowed character. Those are control characters (C0 `0x00`–`0x1F`, DEL `0x7F`, C1 `0x80`–`0x9F`), the Unicode line separators U+2028 and U+2029, and the replacement character U+FFFD. An escaped unpaired surrogate decodes to U+FFFD, so it is rejected too. Text pasted from a PDF, or left behind by a lossy re-encode, often carries one of these invisibly.

Not sending the header at all, or sending it with an empty value, isn't an error condition — both are simply "no attribution," the same outcome as a header that's out of scope for your client.

## Confirming it was received

Because the request succeeds regardless of whether `X-Agent-Info` parsed, check the `x-agent-info-status` response header to confirm your header was actually recognized:
Comment on lines +47 to +53

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the PR description, some of these parse rules ("Several parse rules are also missing or stated in the wrong unit") may not match the shipped parser (xagentinfo.go in Uniswap/backend). I can't independently check that private repo from here, so I can't confirm which specific bullet(s) are off (e.g. the 1024-byte cap, the ASCII range check, the 256 UTF-16 code unit limit, or the disallowed-character set). Someone with access to the current backend implementation should diff each bullet against the real validation logic before merging — a wrong limit here (e.g. byte cap vs. character cap) would cause integrators' otherwise-valid headers to silently fail attribution.


- **`x-agent-info-status: malformed`** — the header was received but failed one of the checks above and was dropped. The value is always the fixed string `malformed`; it never echoes anything from your request.
- **No `x-agent-info-status` header at all** — your `X-Agent-Info` header parsed, or you didn't send one.

The gateway sets this header after it routes your request, and before it writes its own response. Error responses carry it too — a 400, a 401, a 403, a 429, and a 404 for a path that does not exist. So you can debug the header without first getting a working quote. A CORS preflight carries no status header, because the gateway answers it before it looks at `X-Agent-Info`.

Call the Trading API server-to-server. The gateway sends CORS headers only to a small allow-list of origins, so a browser page on your own domain cannot read this header. Check it from a server or with curl.

```typescript
const response = await fetch('https://trade-api.gateway.uniswap.org/v1/quote', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
'X-Agent-Info': JSON.stringify({
decision_origin: 'autonomous',
integration_name: 'my-trading-bot',
version: '1.4.0',
}),
},
body: JSON.stringify({
tokenIn: '0x...',
tokenOut: '0x...',
tokenInChainId: 1,
tokenOutChainId: 1,
type: 'EXACT_INPUT',
amount: '1000000',
swapper: '0x...',
slippageTolerance: 0.5,
}),
});

if (response.headers.get('x-agent-info-status') === 'malformed') {
// Received but dropped — check field names, decision_origin value, and length limits above.
console.warn('X-Agent-Info was sent but not recognized.');
}

const quote = await response.json();
```
Comment thread
wkoutre marked this conversation as resolved.
Comment on lines +57 to +92

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire section describes an x-agent-info-status response header, including exact values (malformed), timing guarantees relative to CORS preflight and error responses (400/401/403/429/404), and a worked TypeScript example that branches on it. If this header was never actually shipped (see comment on the frontmatter above — the PR description says the implementing PR was closed unmerged and superseded by a gateway-only parser), this whole section is fabricated behavior that will mislead integrators: they'll write code that checks a header that never arrives and silently always treat requests as unattributed. This should be corrected or removed before merge, not just flagged in the PR description.


The only consequence of a malformed header is that your traffic isn't attributed to your integration.
4 changes: 3 additions & 1 deletion content/trading/swapping-api/common-errors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ description: Troubleshoot common Uniswap API request, quoting, authentication, a

The API is specific about request header validation. In particular, ensure that your `accept` and `content-type` headers only include the value `application/json`. For a complete example of properly formatted request headers, see the authentication section of the [Developer Dashboard](https://developers.uniswap.org/dashboard).

If you're sending the optional `X-Agent-Info` attribution header and it isn't being picked up, check the response for an `x-agent-info-status: malformed` header — see [Agent Attribution](/docs/trading/swapping-api/agent-attribution#confirming-it-was-received) for the full set of rules that make the header malformed. A malformed `X-Agent-Info` never causes an error response; the request proceeds without attribution.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also references the x-agent-info-status: malformed response header. If that header turns out not to exist in production (see the flag on agent-attribution.mdx), this troubleshooting tip should be reverted along with the new page.


### Rate limits

Most API keys have a default rate limit of 6 requests per second (RPS). If you exceed the rate limit supported by an API key you can expect to receive an HTTP 429 error. If you receive a 429 error, we recommend pausing all requests from your API key and then retrying your requests. If you require a higher rate limit than what your API key is currently provisioned for, please reach out to [Uniswap Developer Support](https://support.uniswap.org/hc/en-us/requests/new). For more information on rate limits, see the [Developer Dashboard](https://developers.uniswap.org/dashboard).
Expand All @@ -25,7 +27,7 @@ The most commonly encountered HTTP error is an HTTP 404 with a message "No quote

### 400 Request validation error

Request validation errors are returned when a request does not contain the minimum required set of fields or has other syntactical errors. Some examples are a required field (ex. `autoSlippage` in the [`/quote`](/docs/trading/swapping-api/getting-started) endpoint) is not populated, or an address is missing a character (eg. is 39 characters long instead of 40). These errors typically include a specific error message which describes the field which could not be interpreted.
Request validation errors are returned when a request does not contain the minimum required set of fields or has other syntactical errors. Some examples are a required field is not populated ([`/quote`](/docs/trading/swapping-api/getting-started) requires `type`, `amount`, `tokenInChainId`, `tokenOutChainId`, `tokenIn`, `tokenOut`, and `swapper`), or an address is missing a character (eg. is 39 characters long instead of 40). These errors typically include a specific error message which describes the field which could not be interpreted.

### 401 Unauthorized error

Expand Down
2 changes: 2 additions & 0 deletions content/trading/swapping-api/integration-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ const quote = await response.json();

AI builders can consume the full Open API Specification (OAS) at [https://trade-api.gateway.uniswap.org/v1/api.json](https://trade-api.gateway.uniswap.org/v1/api.json).

If your integration is built or operated by an AI agent, also consider sending the optional [`X-Agent-Info` attribution header](/docs/trading/swapping-api/agent-attribution) alongside your request.

Full code examples for completing a basic swap workflow are available in [Swapping Code Examples](/docs/trading/swapping-api/swapping-code-examples).

## Architecture
Expand Down
1 change: 1 addition & 0 deletions content/trading/swapping-api/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"concepts",
"supported-chains",
"integration-guide",
"agent-attribution",
"chained-actions",
"chained-actions-integration",
"amm-vs-uniswapx-routing",
Expand Down
4 changes: 3 additions & 1 deletion content/uniswap-ai/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ description: Get started with Uniswap AI plugins, skills, and LLM context.

Use Uniswap AI to speed up swap integration, hook development, and EVM workflows with tools designed for builders on Uniswap.

If your agent talks to the Trading API directly, send the optional [`X-Agent-Info` attribution header](/docs/trading/swapping-api/agent-attribution) so agent-driven traffic is measured separately from human-driven traffic.

## Uniswap AI

The [Uniswap AI repository](https://github.com/Uniswap/uniswap-ai) is an open-source collection of plugins and skills for coding agents. It provides protocol-specific guidance for Uniswap APIs and smart contracts.
Expand Down Expand Up @@ -95,7 +97,7 @@ https://developers.uniswap.org/llms-full.txt

### Claude Code

Install the Uniswap AI plugins (see [above](#install-as-a-claude-code-plugin)) for the richest integration. The plugins provide structured skills, expert agents, and protocol-specific tools that go beyond static documentation context.
Install the Uniswap AI plugins (see [above](#claude-code-marketplace)) for the richest integration. The plugins provide structured skills, expert agents, and protocol-specific tools that go beyond static documentation context.

## Where to Go Next

Expand Down
Loading