Thank you for your interest in contributing to CDP Agentkit! We welcome all contributions, no matter how big or small. Some of the ways you can contribute include:
- Adding new actions to the core package
- Updating existing Langchain Toolkits or adding new Langchain Toolkits to support new tools
- Creating new AI frameworks extensions
- Adding tests and improving documentation
Clone the repo by running:
git clone git@github.com:coinbase/cdp-agentkit.git
- Python 3.10 or higher
- Rust/Cargo installed (Rust Installation Instructions)
- Poetry for package management and tooling
cdp-langchain
also requires a CDP API Key.
make format
-
Check linter
make lint
-
Fix linter errors
make lint-fix
- Run unit tests
make test
- Node.js 18 or higher
- npm for package management
Install dependencies:
npm install
To build all packages:
npm run build
To check for lint errors:
npm run lint
To automatically fix lint errors:
npm run lint-fix
To format code:
npm run format
To run all tests:
npm test
To generate documentation:
npm run docs
All code must follow the project's ESLint and Prettier configurations. The key rules are:
- Use TypeScript
- Follow JSDoc documentation standards
- Use 2 spaces for indentation
- Maximum line length of 100 characters
- Double quotes for strings
- Semicolons required
- Actions are defined in
./cdp-agentkit-core/python/cdp_agentkit_core/actions
module. See./cdp-agentkit-core/python/cdp_agentkit_core/actions/mint_nft.py
for an example. - Actions are created by subclassing
CdpAction
E.g.
class DeployNftAction(CdpAction):
"""Deploy NFT action."""
name: str = "mint_nft"
description: str = MINT_NFT_PROMPT
args_schema: type[BaseModel] | None = MintNftInput
func: Callable[..., str] = mint_nft
name
- Name of the action.description
- A string that will provide the AI Agent with context on what the function does and a natural language description of the input.- E.g.
MINT_NFT_PROMPT = """
This tool will mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation. It takes the contract address of the NFT onchain and the destination address onchain that will receive the NFT as inputs."""
arg_schema
- A Pydantic Model that defines the input argument schema for the action.- E.g.
class MintNftInput(BaseModel):
"""Input argument schema for mint NFT action."""
contract_address: str = Field(
...,
description="The contract address of the NFT (ERC-721) to mint, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`",
)
destination: str = Field(
...,
description="The destination address that will receive the NFT onchain, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`",
)
func
- A function (or Callable class) that executes the action.- E.g.
def mint_nft(wallet: Wallet, contract_address: str, destination: str) -> str:
"""Mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation.
Args:
wallet (Wallet): The wallet to trade the asset from.
contract_address (str): The contract address of the NFT (ERC-721) to mint, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`.
destination (str): The destination address that will receive the NFT onchain, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`.
Returns:
str: A message containing the NFT mint details.
"""
mint_args = {"to": destination, "quantity": "1"}
mint_invocation = wallet.invoke_contract(
contract_address=contract_address, method="mint", args=mint_args
).wait()
return f"Minted NFT from contract {contract_address} to address {destination} on network {wallet.network_id}.\nTransaction hash for the mint: {mint_invocation.transaction.transaction_hash}\nTransaction link for the mint: {mint_invocation.transaction.transaction_link}"
Actions are defined in cdp-agentkit-core/typescript/src/actions
module. See cdp-agentkit-core/typescript/src/actions/cdp/mint_nft.ts
for an example.
Actions are created by implementing the CdpAction
interface:
import { CdpAction } from "./cdp_action";
import { Wallet } from "@coinbase/coinbase-sdk";
import { z } from "zod";
const MINT_NFT_PROMPT = `
This tool will mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation. It takes the contract address of the NFT onchain and the destination address onchain that will receive the NFT as inputs. Do not use the contract address as the destination address. If you are unsure of the destination address, please ask the user before proceeding.`;
/**
* Input schema for mint NFT action.
*/
const MintNftInput = z
.object({
contractAddress: z.string().describe("The contract address of the NFT to mint"),
destination: z.string().describe("The destination address that will receive the NFT"),
})
.strip()
.describe("Instructions for minting an NFT");
/**
* Mints an NFT (ERC-721) to a specified destination address onchain.
*
* @param wallet - The wallet to mint the NFT from.
* @param args - The input arguments for the action.
* @returns A message containing the NFT mint details.
*/
async function mintNft(wallet: Wallet, args: z.infer<typeof MintNftInput>): Promise<string> {
const mintArgs = {
to: args.destination,
quantity: "1",
};
try {
const mintInvocation = await wallet.invokeContract({
contractAddress: args.contractAddress,
method: "mint",
args: mintArgs,
});
const result = await mintInvocation.wait();
return `Minted NFT from contract ${args.contractAddress} to address ${args.destination} on network ${wallet.getNetworkId()}.\nTransaction hash for the mint: ${result.getTransaction().getTransactionHash()}\nTransaction link for the mint: ${result.getTransaction().getTransactionLink()}`;
} catch (error) {
return `Error minting NFT: ${error}`;
}
}
/**
* Mint NFT action.
*/
export class MintNftAction implements CdpAction<typeof MintNftInput> {
public name = "mint_nft";
public description = MINT_NFT_PROMPT;
public argsSchema = MintNftInput;
public func = mintNft;
}
- Input Schema: Define the input parameters using Zod schemas
- Prompt: A description that helps the AI understand when and how to use the action
- Action Class: Implements the
CdpAction
interface with:name
: Unique identifier for the actiondescription
: The prompt textargsSchema
: The Zod schema for validating inputsfunc
: The implementation function
- Implementation Function: The actual logic that executes the action
For both Python and Typescript, follow these steps:
- Ensure the action is implemented in
cdp-agentkit-core
and in a released version. - Update the
cdp-agentkit-core
dependency to the latest version. - Add the action to the list of tools in the
CdpToolkit
class documentation.
- Ensure the action is implemented in
cdp-agentkit-core/actions/social/twitter
. - Add a wrapper method to
TwitterApiWrapper
in./twitter_langchain/twitter_api_wrapper.py
- E.g.
def post_tweet_wrapper(self, tweet: str) -> str:
"""Post tweet to Twitter.
Args:
client (tweepy.Client): The tweepy client to use.
tweet (str): The text of the tweet to post to twitter. Tweets can be maximum 280 characters.
Returns:
str: A message containing the result of the post action and the tweet.
"""
return post_tweet(client=self.client, tweet=tweet)
- Add call to the wrapper in
TwitterApiWrapper.run
in./twitter_langchain/twitter_api_wrapper.py
- E.g.
if mode == "post_tweet":
return self.post_tweet_wrapper(**kwargs)
- Add the action to the list of available tools in the
TwitterToolkit
in./twitter_langchain/twitter_toolkit.py
- E.g.
actions: List[Dict] = [
{
"mode": "post_tweet",
"name": "post_tweet",
"description": POST_TWEET_PROMPT,
"args_schema": PostTweetInput,
},
]
- Update
TwitterToolkit
documentation- Add the action to the list of tools
- Add any additional ENV requirements
- For new features and bug fixes, please add a new changelog entry to the
CHANGELOG.md
file in the appropriate packages and include that in your Pull Request.
- Create a new branch for your changes
- Make your changes following the coding standards
- Add tests for any new functionality
- Update documentation as needed
- Update the CHANGELOG.md
- Submit a pull request
If you have questions or need help, please:
- Check the existing documentation
- Search through existing issues
- Create a new issue with your question
Thank you for contributing to CDP AgentKit!