Skip to content

Commit

Permalink
feat: coinbase agentkit plugin for eliza (#2298)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
Co-authored-by: Sayo <[email protected]>
  • Loading branch information
3 people authored Jan 17, 2025
1 parent 5256560 commit c4d173d
Show file tree
Hide file tree
Showing 12 changed files with 530 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,11 @@ COINBASE_GENERATED_WALLET_ID= # Not your address but the wallet ID from ge
COINBASE_GENERATED_WALLET_HEX_SEED= # Not your address but the wallet hex seed from generating a wallet through the plugin and calling export
COINBASE_NOTIFICATION_URI= # For webhook plugin the uri you want to send the webhook to for dummy ones use https://webhook.site

# Coinbase AgentKit
COINBASE_AGENT_KIT_NETWORK= # defaults to 'base-sepolia'
CDP_API_KEY_NAME=
CDP_API_KEY_PRIVATE_KEY=

# Coinbase Charity Configuration
IS_CHARITABLE=false # Set to true to enable charity donations
CHARITY_ADDRESS_BASE=0x1234567890123456789012345678901234567890
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ tsup.config.bundled_*.mjs
.turbo
.cursorrules
.pnpm-store
instructions.md
wallet_data.txt

coverage
.eslintcache
Expand Down
1 change: 1 addition & 0 deletions agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@elizaos/core": "workspace:*",
"@elizaos/plugin-0g": "workspace:*",
"@elizaos/plugin-abstract": "workspace:*",
"@elizaos/plugin-agentkit": "workspace:*",
"@elizaos/plugin-aptos": "workspace:*",
"@elizaos/plugin-birdeye": "workspace:*",
"@elizaos/plugin-coingecko": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion client/src/lib/info.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version": "0.1.8+build.1"}
{"version": "0.1.9-alpha.1"}
123 changes: 123 additions & 0 deletions packages/plugin-agentkit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# @elizaos/plugin-agentkit

AgentKit plugin for Eliza that enables interaction with CDP AgentKit tools for NFT and token management.

## Setup

1. Install dependencies:

```bash
pnpm install
```

2. Configure environment variables:

```env
CDP_API_KEY_NAME=your_key_name
CDP_API_KEY_PRIVATE_KEY=your_private_key
```

3. Add the plugin to your character configuration:

```json
{
"plugins": ["@ai16z/plugin-agentkit"],
"settings": {
"secrets": {
"CDP_API_KEY_NAME": "your_key_name",
"CDP_API_KEY_PRIVATE_KEY": "your_private_key",
"networkId": "base-sepolia"
}
}
}
```

## Available Tools

The plugin provides access to the following CDP AgentKit tools:

- `GET_WALLET_DETAILS`: Get wallet information
- `DEPLOY_NFT`: Deploy a new NFT collection
- `DEPLOY_TOKEN`: Deploy a new token
- `GET_BALANCE`: Check token or NFT balance
- `MINT_NFT`: Mint NFTs from a collection
- `REGISTER_BASENAME`: Register a basename for NFTs
- `REQUEST_FAUCET_FUNDS`: Request testnet funds
- `TRADE`: Execute trades
- `TRANSFER`: Transfer tokens or NFTs
- `WOW_BUY_TOKEN`: Buy WOW tokens
- `WOW_SELL_TOKEN`: Sell WOW tokens
- `WOW_CREATE_TOKEN`: Create new WOW tokens

## Usage Examples

1. Get wallet details:

```
Can you show me my wallet details?
```

2. Deploy an NFT collection:

```
Deploy a new NFT collection called "Music NFTs" with symbol "MUSIC"
```

3. Create a token:

```
Create a new WOW token called "Artist Token" with symbol "ART"
```

4. Check balance:

```
What's my current balance?
```

## Development

1. Build the plugin:

```bash
pnpm build
```

2. Run in development mode:

```bash
pnpm dev
```

## Dependencies

- @elizaos/core
- @coinbase/cdp-agentkit-core
- @coinbase/cdp-langchain
- @langchain/core

## Network Support

The plugin currently supports the following networks:

- Base Sepolia (default)
- Base Mainnet

Configure the network using the `networkId` setting in your character configuration.

## Troubleshooting

1. If tools are not being triggered:

- Verify CDP API key configuration
- Check network settings
- Ensure character configuration includes the plugin

2. Common errors:
- "Cannot find package": Make sure dependencies are installed
- "API key not found": Check environment variables
- "Network error": Verify network configuration

## License

MIT
18 changes: 18 additions & 0 deletions packages/plugin-agentkit/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "@elizaos/plugin-agentkit",
"version": "0.0.1",
"main": "dist/index.js",
"type": "module",
"types": "dist/index.d.ts",
"dependencies": {
"@elizaos/core": "workspace:*",
"@coinbase/cdp-agentkit-core": "^0.0.10",
"@coinbase/cdp-langchain": "^0.0.11",
"@langchain/core": "^0.3.27",
"tsup": "8.3.5"
},
"scripts": {
"build": "tsup --format esm --dts",
"dev": "tsup --format esm --dts --watch"
}
}
178 changes: 178 additions & 0 deletions packages/plugin-agentkit/src/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import {
type Action,
generateText,
type HandlerCallback,
type IAgentRuntime,
type Memory,
ModelClass,
type State,
composeContext,
generateObject,
} from "@elizaos/core";
import { CdpAgentkit } from "@coinbase/cdp-agentkit-core";
import { CdpToolkit, type Tool } from "@coinbase/cdp-langchain";

type GetAgentKitActionsParams = {
getClient: () => Promise<CdpAgentkit>;
config?: {
networkId?: string;
};
};

/**
* Get all AgentKit actions
*/
export async function getAgentKitActions({
getClient,
}: GetAgentKitActionsParams): Promise<Action[]> {
const agentkit = await getClient();
const cdpToolkit = new CdpToolkit(agentkit);
const tools = cdpToolkit.getTools();
const actions = tools.map((tool: Tool) => ({
name: tool.name.toUpperCase(),
description: tool.description,
similes: [],
validate: async () => true,
handler: async (
runtime: IAgentRuntime,
message: Memory,
state: State | undefined,
options?: Record<string, unknown>,
callback?: HandlerCallback
): Promise<boolean> => {
try {
const client = await getClient();
let currentState =
state ?? (await runtime.composeState(message));
currentState =
await runtime.updateRecentMessageState(currentState);

const parameterContext = composeParameterContext(
tool,
currentState
);
const parameters = await generateParameters(
runtime,
parameterContext,
tool
);

const result = await executeToolAction(
tool,
parameters,
client
);

const responseContext = composeResponseContext(
tool,
result,
currentState
);
const response = await generateResponse(
runtime,
responseContext
);

callback?.({ text: response, content: result });
return true;
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : String(error);
callback?.({
text: `Error executing action ${tool.name}: ${errorMessage}`,
content: { error: errorMessage },
});
return false;
}
},
examples: [],
}));
return actions;
}

async function executeToolAction(
tool: Tool,
parameters: any,
client: CdpAgentkit
): Promise<unknown> {
const toolkit = new CdpToolkit(client);
const tools = toolkit.getTools();
const selectedTool = tools.find((t) => t.name === tool.name);

if (!selectedTool) {
throw new Error(`Tool ${tool.name} not found`);
}

return await selectedTool.call(parameters);
}

function composeParameterContext(tool: any, state: State): string {
const contextTemplate = `{{recentMessages}}
Given the recent messages, extract the following information for the action "${tool.name}":
${tool.description}
`;
return composeContext({ state, template: contextTemplate });
}

async function generateParameters(
runtime: IAgentRuntime,
context: string,
tool: Tool
): Promise<unknown> {
const { object } = await generateObject({
runtime,
context,
modelClass: ModelClass.LARGE,
schema: tool.schema,
});

return object;
}

function composeResponseContext(
tool: Tool,
result: unknown,
state: State
): string {
const responseTemplate = `
# Action Examples
{{actionExamples}}
# Knowledge
{{knowledge}}
# Task: Generate dialog and actions for the character {{agentName}}.
About {{agentName}}:
{{bio}}
{{lore}}
{{providers}}
{{attachments}}
# Capabilities
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.
The action "${tool.name}" was executed successfully.
Here is the result:
${JSON.stringify(result)}
{{actions}}
Respond to the message knowing that the action was successful and these were the previous messages:
{{recentMessages}}
`;
return composeContext({ state, template: responseTemplate });
}

async function generateResponse(
runtime: IAgentRuntime,
context: string
): Promise<string> {
return generateText({
runtime,
context,
modelClass: ModelClass.LARGE,
});
}
16 changes: 16 additions & 0 deletions packages/plugin-agentkit/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Plugin } from "@elizaos/core";
import { walletProvider, getClient } from "./provider";
import { getAgentKitActions } from "./actions";

export const agentKitPlugin: Plugin = {
name: "[AgentKit] Integration",
description: "AgentKit integration plugin",
providers: [walletProvider],
evaluators: [],
services: [],
actions: await getAgentKitActions({
getClient,
}),
};

export default agentKitPlugin;
Loading

0 comments on commit c4d173d

Please sign in to comment.