Skip to content

Commit c4d173d

Browse files
feat: coinbase agentkit plugin for eliza (elizaOS#2298)
* I add files for plugin-agentkit * instructions added to gitignore. * I update package name. * I add updated files. * I add ENV requirements to prevent default Eliza bugs. * rollback index * simple agentkit import. * I load existing wallet data for provider. * remove dev logging * Update pnpm-lock.yaml * update .env.example and support non 'base-sepolia' * Update pnpm-lock.yaml * Update package lock for smoke tests. * I rollback changes to pnpm-lock file. * fixing smoke tests for pnpm missing * rollback changes to agent start file. * I rollback changes to smoke test. * Update pnpm-lock.yaml --------- Co-authored-by: Sayo <82053242+wtfsayo@users.noreply.github.com> Co-authored-by: Sayo <hi@sayo.wtf>
1 parent 5256560 commit c4d173d

File tree

12 files changed

+530
-1
lines changed

12 files changed

+530
-1
lines changed

.env.example

+5
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,11 @@ COINBASE_GENERATED_WALLET_ID= # Not your address but the wallet ID from ge
352352
COINBASE_GENERATED_WALLET_HEX_SEED= # Not your address but the wallet hex seed from generating a wallet through the plugin and calling export
353353
COINBASE_NOTIFICATION_URI= # For webhook plugin the uri you want to send the webhook to for dummy ones use https://webhook.site
354354

355+
# Coinbase AgentKit
356+
COINBASE_AGENT_KIT_NETWORK= # defaults to 'base-sepolia'
357+
CDP_API_KEY_NAME=
358+
CDP_API_KEY_PRIVATE_KEY=
359+
355360
# Coinbase Charity Configuration
356361
IS_CHARITABLE=false # Set to true to enable charity donations
357362
CHARITY_ADDRESS_BASE=0x1234567890123456789012345678901234567890

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ tsup.config.bundled_*.mjs
5252
.turbo
5353
.cursorrules
5454
.pnpm-store
55+
instructions.md
56+
wallet_data.txt
5557

5658
coverage
5759
.eslintcache

agent/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"@elizaos/core": "workspace:*",
3636
"@elizaos/plugin-0g": "workspace:*",
3737
"@elizaos/plugin-abstract": "workspace:*",
38+
"@elizaos/plugin-agentkit": "workspace:*",
3839
"@elizaos/plugin-aptos": "workspace:*",
3940
"@elizaos/plugin-birdeye": "workspace:*",
4041
"@elizaos/plugin-coingecko": "workspace:*",

client/src/lib/info.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"version": "0.1.8+build.1"}
1+
{"version": "0.1.9-alpha.1"}

packages/plugin-agentkit/README.md

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# @elizaos/plugin-agentkit
2+
3+
AgentKit plugin for Eliza that enables interaction with CDP AgentKit tools for NFT and token management.
4+
5+
## Setup
6+
7+
1. Install dependencies:
8+
9+
```bash
10+
pnpm install
11+
```
12+
13+
2. Configure environment variables:
14+
15+
```env
16+
CDP_API_KEY_NAME=your_key_name
17+
CDP_API_KEY_PRIVATE_KEY=your_private_key
18+
```
19+
20+
3. Add the plugin to your character configuration:
21+
22+
```json
23+
{
24+
"plugins": ["@ai16z/plugin-agentkit"],
25+
"settings": {
26+
"secrets": {
27+
"CDP_API_KEY_NAME": "your_key_name",
28+
"CDP_API_KEY_PRIVATE_KEY": "your_private_key",
29+
"networkId": "base-sepolia"
30+
}
31+
}
32+
}
33+
```
34+
35+
## Available Tools
36+
37+
The plugin provides access to the following CDP AgentKit tools:
38+
39+
- `GET_WALLET_DETAILS`: Get wallet information
40+
- `DEPLOY_NFT`: Deploy a new NFT collection
41+
- `DEPLOY_TOKEN`: Deploy a new token
42+
- `GET_BALANCE`: Check token or NFT balance
43+
- `MINT_NFT`: Mint NFTs from a collection
44+
- `REGISTER_BASENAME`: Register a basename for NFTs
45+
- `REQUEST_FAUCET_FUNDS`: Request testnet funds
46+
- `TRADE`: Execute trades
47+
- `TRANSFER`: Transfer tokens or NFTs
48+
- `WOW_BUY_TOKEN`: Buy WOW tokens
49+
- `WOW_SELL_TOKEN`: Sell WOW tokens
50+
- `WOW_CREATE_TOKEN`: Create new WOW tokens
51+
52+
## Usage Examples
53+
54+
1. Get wallet details:
55+
56+
```
57+
Can you show me my wallet details?
58+
```
59+
60+
2. Deploy an NFT collection:
61+
62+
```
63+
Deploy a new NFT collection called "Music NFTs" with symbol "MUSIC"
64+
```
65+
66+
3. Create a token:
67+
68+
```
69+
Create a new WOW token called "Artist Token" with symbol "ART"
70+
```
71+
72+
4. Check balance:
73+
74+
```
75+
What's my current balance?
76+
```
77+
78+
## Development
79+
80+
1. Build the plugin:
81+
82+
```bash
83+
pnpm build
84+
```
85+
86+
2. Run in development mode:
87+
88+
```bash
89+
pnpm dev
90+
```
91+
92+
## Dependencies
93+
94+
- @elizaos/core
95+
- @coinbase/cdp-agentkit-core
96+
- @coinbase/cdp-langchain
97+
- @langchain/core
98+
99+
## Network Support
100+
101+
The plugin currently supports the following networks:
102+
103+
- Base Sepolia (default)
104+
- Base Mainnet
105+
106+
Configure the network using the `networkId` setting in your character configuration.
107+
108+
## Troubleshooting
109+
110+
1. If tools are not being triggered:
111+
112+
- Verify CDP API key configuration
113+
- Check network settings
114+
- Ensure character configuration includes the plugin
115+
116+
2. Common errors:
117+
- "Cannot find package": Make sure dependencies are installed
118+
- "API key not found": Check environment variables
119+
- "Network error": Verify network configuration
120+
121+
## License
122+
123+
MIT

packages/plugin-agentkit/package.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "@elizaos/plugin-agentkit",
3+
"version": "0.0.1",
4+
"main": "dist/index.js",
5+
"type": "module",
6+
"types": "dist/index.d.ts",
7+
"dependencies": {
8+
"@elizaos/core": "workspace:*",
9+
"@coinbase/cdp-agentkit-core": "^0.0.10",
10+
"@coinbase/cdp-langchain": "^0.0.11",
11+
"@langchain/core": "^0.3.27",
12+
"tsup": "8.3.5"
13+
},
14+
"scripts": {
15+
"build": "tsup --format esm --dts",
16+
"dev": "tsup --format esm --dts --watch"
17+
}
18+
}
+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
import {
2+
type Action,
3+
generateText,
4+
type HandlerCallback,
5+
type IAgentRuntime,
6+
type Memory,
7+
ModelClass,
8+
type State,
9+
composeContext,
10+
generateObject,
11+
} from "@elizaos/core";
12+
import { CdpAgentkit } from "@coinbase/cdp-agentkit-core";
13+
import { CdpToolkit, type Tool } from "@coinbase/cdp-langchain";
14+
15+
type GetAgentKitActionsParams = {
16+
getClient: () => Promise<CdpAgentkit>;
17+
config?: {
18+
networkId?: string;
19+
};
20+
};
21+
22+
/**
23+
* Get all AgentKit actions
24+
*/
25+
export async function getAgentKitActions({
26+
getClient,
27+
}: GetAgentKitActionsParams): Promise<Action[]> {
28+
const agentkit = await getClient();
29+
const cdpToolkit = new CdpToolkit(agentkit);
30+
const tools = cdpToolkit.getTools();
31+
const actions = tools.map((tool: Tool) => ({
32+
name: tool.name.toUpperCase(),
33+
description: tool.description,
34+
similes: [],
35+
validate: async () => true,
36+
handler: async (
37+
runtime: IAgentRuntime,
38+
message: Memory,
39+
state: State | undefined,
40+
options?: Record<string, unknown>,
41+
callback?: HandlerCallback
42+
): Promise<boolean> => {
43+
try {
44+
const client = await getClient();
45+
let currentState =
46+
state ?? (await runtime.composeState(message));
47+
currentState =
48+
await runtime.updateRecentMessageState(currentState);
49+
50+
const parameterContext = composeParameterContext(
51+
tool,
52+
currentState
53+
);
54+
const parameters = await generateParameters(
55+
runtime,
56+
parameterContext,
57+
tool
58+
);
59+
60+
const result = await executeToolAction(
61+
tool,
62+
parameters,
63+
client
64+
);
65+
66+
const responseContext = composeResponseContext(
67+
tool,
68+
result,
69+
currentState
70+
);
71+
const response = await generateResponse(
72+
runtime,
73+
responseContext
74+
);
75+
76+
callback?.({ text: response, content: result });
77+
return true;
78+
} catch (error) {
79+
const errorMessage =
80+
error instanceof Error ? error.message : String(error);
81+
callback?.({
82+
text: `Error executing action ${tool.name}: ${errorMessage}`,
83+
content: { error: errorMessage },
84+
});
85+
return false;
86+
}
87+
},
88+
examples: [],
89+
}));
90+
return actions;
91+
}
92+
93+
async function executeToolAction(
94+
tool: Tool,
95+
parameters: any,
96+
client: CdpAgentkit
97+
): Promise<unknown> {
98+
const toolkit = new CdpToolkit(client);
99+
const tools = toolkit.getTools();
100+
const selectedTool = tools.find((t) => t.name === tool.name);
101+
102+
if (!selectedTool) {
103+
throw new Error(`Tool ${tool.name} not found`);
104+
}
105+
106+
return await selectedTool.call(parameters);
107+
}
108+
109+
function composeParameterContext(tool: any, state: State): string {
110+
const contextTemplate = `{{recentMessages}}
111+
112+
Given the recent messages, extract the following information for the action "${tool.name}":
113+
${tool.description}
114+
`;
115+
return composeContext({ state, template: contextTemplate });
116+
}
117+
118+
async function generateParameters(
119+
runtime: IAgentRuntime,
120+
context: string,
121+
tool: Tool
122+
): Promise<unknown> {
123+
const { object } = await generateObject({
124+
runtime,
125+
context,
126+
modelClass: ModelClass.LARGE,
127+
schema: tool.schema,
128+
});
129+
130+
return object;
131+
}
132+
133+
function composeResponseContext(
134+
tool: Tool,
135+
result: unknown,
136+
state: State
137+
): string {
138+
const responseTemplate = `
139+
# Action Examples
140+
{{actionExamples}}
141+
142+
# Knowledge
143+
{{knowledge}}
144+
145+
# Task: Generate dialog and actions for the character {{agentName}}.
146+
About {{agentName}}:
147+
{{bio}}
148+
{{lore}}
149+
150+
{{providers}}
151+
152+
{{attachments}}
153+
154+
# Capabilities
155+
Note that {{agentName}} is capable of reading/seeing/hearing various forms of media, including images, videos, audio, plaintext and PDFs. Recent attachments have been included above under the "Attachments" section.
156+
157+
The action "${tool.name}" was executed successfully.
158+
Here is the result:
159+
${JSON.stringify(result)}
160+
161+
{{actions}}
162+
163+
Respond to the message knowing that the action was successful and these were the previous messages:
164+
{{recentMessages}}
165+
`;
166+
return composeContext({ state, template: responseTemplate });
167+
}
168+
169+
async function generateResponse(
170+
runtime: IAgentRuntime,
171+
context: string
172+
): Promise<string> {
173+
return generateText({
174+
runtime,
175+
context,
176+
modelClass: ModelClass.LARGE,
177+
});
178+
}

packages/plugin-agentkit/src/index.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { Plugin } from "@elizaos/core";
2+
import { walletProvider, getClient } from "./provider";
3+
import { getAgentKitActions } from "./actions";
4+
5+
export const agentKitPlugin: Plugin = {
6+
name: "[AgentKit] Integration",
7+
description: "AgentKit integration plugin",
8+
providers: [walletProvider],
9+
evaluators: [],
10+
services: [],
11+
actions: await getAgentKitActions({
12+
getClient,
13+
}),
14+
};
15+
16+
export default agentKitPlugin;

0 commit comments

Comments
 (0)