Skip to content

Commit a3afda3

Browse files
authored
Add 8004 action provider (#930)
* add 8004 action provider * use agent0 sdk for search * bump agent0 sdk * use agent0 sdk for onchain txs * improve search * bump agent0
1 parent 8ec4a85 commit a3afda3

27 files changed

Lines changed: 7581 additions & 446 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@coinbase/agentkit": patch
3+
---
4+
5+
Added erc8004 action providers

typescript/agentkit/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,47 @@ const agent = createAgent({
368368
</table>
369369
</details>
370370
<details>
371+
<summary><strong>ERC-8004</strong></summary>
372+
<table width="100%">
373+
<tr>
374+
<td width="200"><code>append_response</code></td>
375+
<td width="768">Appends an off-chain response URI to a reputation feedback entry (ERC-8004 Reputation Registry).</td>
376+
</tr>
377+
<tr>
378+
<td width="200"><code>get_agent_feedback</code></td>
379+
<td width="768">Lists feedback for an agent with optional filters (reviewers, value range, tags).</td>
380+
</tr>
381+
<tr>
382+
<td width="200"><code>get_agent_info</code></td>
383+
<td width="768">Returns identity, endpoints, capabilities, reputation summary, and status for a registered agent.</td>
384+
</tr>
385+
<tr>
386+
<td width="200"><code>get_owned_agents</code></td>
387+
<td width="768">Lists agents owned by a wallet address (defaults to the connected wallet).</td>
388+
</tr>
389+
<tr>
390+
<td width="200"><code>give_feedback</code></td>
391+
<td width="768">Submits on-chain feedback (and optional IPFS payload) for an agent; cannot be used on your own agent.</td>
392+
</tr>
393+
<tr>
394+
<td width="200"><code>register_agent</code></td>
395+
<td width="768">Registers a new agent on the ERC-8004 Identity Registry (mint NFT and set registration URI).</td>
396+
</tr>
397+
<tr>
398+
<td width="200"><code>revoke_feedback</code></td>
399+
<td width="768">Revokes feedback previously submitted by the connected wallet.</td>
400+
</tr>
401+
<tr>
402+
<td width="200"><code>search_agents</code></td>
403+
<td width="768">Discovers agents via semantic search, capability/status filters, reputation bounds, sort, and pagination.</td>
404+
</tr>
405+
<tr>
406+
<td width="200"><code>update_agent_metadata</code></td>
407+
<td width="768">Updates agent metadata, endpoints (MCP/A2A), trust models, taxonomies, and status flags.</td>
408+
</tr>
409+
</table>
410+
</details>
411+
<details>
371412
<summary><strong>ERC20</strong></summary>
372413
<table width="100%">
373414
<tr>

typescript/agentkit/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"@zerodev/sdk": "^5.4.28",
6161
"@zoralabs/coins-sdk": "0.2.8",
6262
"@zoralabs/protocol-deployments": "0.6.1",
63+
"agent0-sdk": "^1.7.1",
6364
"bs58": "^4.0.1",
6465
"canonicalize": "^2.1.0",
6566
"clanker-sdk": "^4.1.18",

typescript/agentkit/src/action-providers/across/acrossActionProvider.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export class AcrossActionProvider extends ActionProvider<EvmWalletProvider> {
127127
throw new Error(`No input tokens available on chain ${originChain.id}`);
128128
}
129129
const tokenInfo = inputTokens.find(
130-
token => token.symbol.toUpperCase() === (args.inputTokenSymbol ?? "ETH").toUpperCase(),
130+
token => token.symbol.toUpperCase() === args.inputTokenSymbol.toUpperCase(),
131131
);
132132
if (!tokenInfo) {
133133
throw new Error(
@@ -141,7 +141,7 @@ export class AcrossActionProvider extends ActionProvider<EvmWalletProvider> {
141141
const inputAmount = parseUnits(args.amount, decimals);
142142

143143
// Check balance
144-
const isNative = (args.inputTokenSymbol ?? "ETH").toUpperCase() === "ETH";
144+
const isNative = args.inputTokenSymbol.toUpperCase() === "ETH";
145145
if (isNative) {
146146
// Check native ETH balance
147147
const ethBalance = await walletProvider.getBalance();
@@ -212,7 +212,7 @@ export class AcrossActionProvider extends ActionProvider<EvmWalletProvider> {
212212
((Number(formattedInfo.inputAmount) - Number(formattedInfo.outputAmount)) /
213213
Number(formattedInfo.inputAmount)) *
214214
100;
215-
if (actualSlippagePercentage > (args.maxSplippage ?? 1.5)) {
215+
if (actualSlippagePercentage > args.maxSplippage) {
216216
throw new Error(
217217
`Output amount has high slippage of ${actualSlippagePercentage.toFixed(2)}%, which exceeds the maximum allowed slippage of ${args.maxSplippage}%. ` +
218218
`Input: ${formattedInfo.inputAmount} ${args.inputTokenSymbol}, Output: ${formattedInfo.outputAmount} ${args.inputTokenSymbol}`,

typescript/agentkit/src/action-providers/across/schemas.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const BridgeTokenSchema = z
2424
.number()
2525
.nullable()
2626
.transform(val => val ?? 1.5)
27-
.describe("The maximum slippage percentage (e.g. 10 for 10%)"),
27+
.describe("The maximum slippage percentage (e.g. 10 for 10%), defaults to 1.5%"),
2828
})
2929
.describe("Instructions for bridging tokens across chains using Across Protocol");
3030

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# ERC-8004 Action Providers
2+
3+
This directory contains **ERC8004IdentityActionProvider** and **ERC8004ReputationActionProvider**, which expose actions for the [ERC-8004](https://eips.ethereum.org/EIPS/eip-8004) trustless agent registries (identity and reputation) on supported EVM networks. Implementation uses the Agent0 SDK (`getAgent0SDK`).
4+
5+
## Directory Structure
6+
7+
```
8+
erc8004/
9+
├── erc8004IdentityActionProvider.ts # Identity registry: register, metadata, discovery
10+
├── erc8004IdentityActionProvider.test.ts
11+
├── erc8004ReputationActionProvider.ts # Reputation registry: feedback, responses, queries
12+
├── erc8004ReputationActionProvider.test.ts
13+
├── identitySchemas.ts # Zod schemas for identity actions
14+
├── reputationSchemas.ts # Zod schemas for reputation actions
15+
├── constants.ts # Supported network IDs and helpers
16+
├── utils.ts # Agent0 SDK wiring
17+
├── index.ts # Public exports
18+
└── README.md # This file
19+
```
20+
21+
## Providers
22+
23+
Register both providers on an `EvmWalletProvider` when you want full ERC-8004 coverage:
24+
25+
```typescript
26+
import {
27+
erc8004IdentityActionProvider,
28+
erc8004ReputationActionProvider,
29+
} from "@coinbase/agentkit";
30+
31+
const identity = erc8004IdentityActionProvider({ pinataJwt: process.env.PINATA_JWT });
32+
const reputation = erc8004ReputationActionProvider({ pinataJwt: process.env.PINATA_JWT });
33+
```
34+
35+
Optional `pinataJwt` enables IPFS uploads for richer metadata and off-chain feedback payloads (comments, A2A task fields).
36+
37+
## Identity actions (`erc8004_identity`)
38+
39+
- `register_agent`: Mint an agent NFT on the Identity Registry and set registration JSON / URI.
40+
41+
- `update_agent_metadata`: Patch agent configuration (name, description, image, MCP/A2A endpoints, ENS, active/x402 flags, trust models, OASF taxonomies, custom metadata).
42+
43+
- `get_owned_agents`: List agents owned by an address (defaults to the connected wallet).
44+
45+
- `search_agents`: Discover agents via semantic keyword search, filters (capabilities, status, reputation), sort, and pagination.
46+
47+
- `get_agent_info`: Fetch full agent profile (identity, endpoints, capabilities, reputation summary, status).
48+
49+
## Reputation actions (`erc8004_reputation`)
50+
51+
- `give_feedback`: Submit scored feedback (tags, endpoint, optional comment / A2A context); core data on-chain, optional IPFS file when JWT is set. Callers cannot rate their own agent.
52+
53+
- `revoke_feedback`: Revoke feedback previously sent from the connected wallet.
54+
55+
- `append_response`: Append an off-chain response URI to a feedback entry (agent owners, aggregators, auditors, etc., per spec).
56+
57+
- `get_agent_feedback`: Read feedback for an agent with optional filters (reviewers, value range, tags).
58+
59+
## Adding New Actions
60+
61+
1. Add or extend Zod schemas in `identitySchemas.ts` or `reputationSchemas.ts`. See [Defining the input schema](https://github.com/coinbase/agentkit/blob/main/CONTRIBUTING-TYPESCRIPT.md#defining-the-input-schema).
62+
2. Implement the action on `ERC8004IdentityActionProvider` or `ERC8004ReputationActionProvider` with `@CreateAction`.
63+
3. Cover behavior in the matching `*.test.ts` file.
64+
65+
## Network Support
66+
67+
Supported `networkId` values are defined in `constants.ts` (e.g. Ethereum and Base mainnet/sepolia, Polygon mainnet). Other networks are rejected by `supportsNetwork`.
68+
69+
## Notes
70+
71+
- Agent IDs may be passed as a local token id (e.g. `"123"`) or as `"chainId:tokenId"` (e.g. `"84532:123"`).
72+
- For broader setup and examples, see the AgentKit [8004 guide](../../../../8004.md) in this repo.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { NETWORK_ID_TO_CHAIN_ID, Network } from "../../network";
2+
3+
// Supported network IDs for ERC-8004 - must match agent0 SDK (contracts.ts DEFAULT_REGISTRIES)
4+
export const SUPPORTED_NETWORK_IDS = [
5+
"ethereum-mainnet", // 1
6+
"ethereum-sepolia", // 11155111
7+
"base-mainnet", // 8453
8+
"base-sepolia", // 84532
9+
"polygon-mainnet", // 137
10+
] as const;
11+
12+
export type SupportedNetworkId = (typeof SUPPORTED_NETWORK_IDS)[number];
13+
14+
/**
15+
* Gets the chain ID from a network object
16+
*
17+
* @param network - The network object
18+
* @returns The chain ID as a number
19+
* @throws Error if network is not supported
20+
*/
21+
export function getChainIdFromNetwork(network: Network): number {
22+
const networkId = network.networkId;
23+
if (!networkId) {
24+
throw new Error("Network ID is not defined");
25+
}
26+
27+
const chainIdStr = NETWORK_ID_TO_CHAIN_ID[networkId];
28+
if (!chainIdStr) {
29+
throw new Error(
30+
`Network ${networkId} is not supported. Supported networks: ${SUPPORTED_NETWORK_IDS.join(", ")}`,
31+
);
32+
}
33+
34+
return parseInt(chainIdStr, 10);
35+
}
36+
37+
/**
38+
* Checks if a network is supported for ERC-8004
39+
*
40+
* @param network - The network to check
41+
* @returns True if the network is supported
42+
*/
43+
export function isNetworkSupported(network: Network): boolean {
44+
const networkId = network.networkId;
45+
if (!networkId) return false;
46+
return SUPPORTED_NETWORK_IDS.includes(networkId as SupportedNetworkId);
47+
}

0 commit comments

Comments
 (0)