Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: coinbase agentkit plugin for eliza #2298

Merged
merged 31 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1e986c8
I add files for plugin-agentkit
sweetmantech Jan 14, 2025
83f4d34
instructions added to gitignore.
sweetmantech Jan 14, 2025
116606e
I update package name.
sweetmantech Jan 14, 2025
3252d84
Merge pull request #5 from sweetmantech/sweets/agentkit
sweetmantech Jan 14, 2025
dfb7d11
I add updated files.
sweetmantech Jan 14, 2025
f2c2506
Merge branch 'main' of github.com:sweetmantech/eliza into sweets/fixes
sweetmantech Jan 14, 2025
3fd80d2
I add ENV requirements to prevent default Eliza bugs.
sweetmantech Jan 14, 2025
5ebeb11
rollback index
sweetmantech Jan 14, 2025
8aab8c0
simple agentkit import.
sweetmantech Jan 14, 2025
bf8d1cb
Merge pull request #6 from sweetmantech/sweets/fixes
sweetmantech Jan 14, 2025
e4ff9a3
I fix pnpm lockfile errors.
sweetmantech Jan 14, 2025
587c1df
Merge pull request #7 from sweetmantech/sweets/pnpm
sweetmantech Jan 14, 2025
6c6d0a4
I load existing wallet data for provider.
sweetmantech Jan 15, 2025
e3004f2
develop merge
sweetmantech Jan 15, 2025
e1b990d
remove dev logging
sweetmantech Jan 16, 2025
c93b317
Merge branch 'develop' into pr/2298
wtfsayo Jan 16, 2025
725f05f
Update pnpm-lock.yaml
wtfsayo Jan 16, 2025
cbef3d8
update .env.example and support non 'base-sepolia'
wtfsayo Jan 16, 2025
b8b6785
Update pnpm-lock.yaml
wtfsayo Jan 16, 2025
234be18
Merge branch 'develop' into main
wtfsayo Jan 16, 2025
aaa1e3c
Merge branch 'develop' into main
sweetmantech Jan 16, 2025
7cbe99f
Update package lock for smoke tests.
sweetmantech Jan 16, 2025
e95254f
Merge branch 'develop' into main
wtfsayo Jan 16, 2025
e080c83
I rollback changes to pnpm-lock file.
sweetmantech Jan 16, 2025
fe81ad4
Merge branch 'main' of github.com:sweetmantech/eliza
sweetmantech Jan 16, 2025
684a7fb
fixing smoke tests for pnpm missing
sweetmantech Jan 16, 2025
b7967b3
rollback changes to agent start file.
sweetmantech Jan 16, 2025
3b14ef3
I rollback changes to smoke test.
sweetmantech Jan 16, 2025
0715eb4
Merge branch 'develop' into main
sweetmantech Jan 16, 2025
56155d6
Merge branch 'develop' into pr/2298
wtfsayo Jan 17, 2025
57ebb77
Update pnpm-lock.yaml
wtfsayo Jan 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ tsup.config.bundled_*.mjs
.turbo
.cursorrules
.pnpm-store
instructions.md

coverage
.eslintcache
Expand Down
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"],
wtfsayo marked this conversation as resolved.
Show resolved Hide resolved
"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"
}
}
183 changes: 183 additions & 0 deletions packages/plugin-agentkit/src/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
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,
config,
}: GetAgentKitActionsParams): Promise<Action[]> {
const agentkit = await getClient();
const cdpToolkit = new CdpToolkit(agentkit);
const tools = cdpToolkit.getTools();
console.log("SWEETMAN------------------------");

const actions = tools.map((tool: Tool) => ({
name: tool.name.toUpperCase(),
description: tool.description,
similes: [],
validate: async () => true,
sweetmantech marked this conversation as resolved.
Show resolved Hide resolved
handler: async (
runtime: IAgentRuntime,
message: Memory,
state: State | undefined,
options?: Record<string, unknown>,
callback?: HandlerCallback
): Promise<boolean> => {
try {
const client = await getClient();
console.log("SWEETMAN CLIENT------------------------", client);
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: [],
}));
console.log("SWEETMAN ACTIONS------------------------", actions);
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);
}
sweetmantech marked this conversation as resolved.
Show resolved Hide resolved

function composeParameterContext(tool: any, state: State): string {
sweetmantech marked this conversation as resolved.
Show resolved Hide resolved
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,
});
}
19 changes: 19 additions & 0 deletions packages/plugin-agentkit/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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({
wtfsayo marked this conversation as resolved.
Show resolved Hide resolved
getClient,
config: {
networkId: "base-sepolia",
},
}),
};

export default agentKitPlugin;
22 changes: 22 additions & 0 deletions packages/plugin-agentkit/src/provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { type Provider, type IAgentRuntime } from "@elizaos/core";
import { CdpAgentkit } from "@coinbase/cdp-agentkit-core";

export async function getClient(): Promise<CdpAgentkit> {
const config = {
networkId: "base-sepolia",
};
return await CdpAgentkit.configureWithWallet(config);
}

export const walletProvider: Provider = {
async get(runtime: IAgentRuntime): Promise<string | null> {
try {
const client = await getClient();
const address = (await (client as any).wallet.addresses)[0].id;
wtfsayo marked this conversation as resolved.
Show resolved Hide resolved
return `AgentKit Wallet Address: ${address}`;
} catch (error) {
console.error("Error in AgentKit provider:", error);
return null;
}
},
};
9 changes: 9 additions & 0 deletions packages/plugin-agentkit/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "../core/tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "./src",
"declaration": true
},
"include": ["src"]
}
Loading
Loading