Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 806
chore: update CONTRIBUTING.md#144
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,228 @@ | ||
| # Python Development Guide | ||
| This guide covers Python-specific setup and development for AgentKit. | ||
| ## Contents | ||
| - [Development Setup](#development-setup) | ||
| - [Adding an Agentic Action](#adding-an-agentic-action) | ||
| - [Adding an Agentic Action to Langchain Toolkit](#adding-an-agentic-action-to-langchain-toolkit) | ||
| - [Adding an Agentic Action to the Twitter Toolkit](#adding-an-agentic-action-to-the-twitter-toolkit) | ||
| - [Testing](#testing) | ||
| - [Code Style](#code-style) | ||
| ## Development Setup | ||
| AgentKit uses Python 3.10 or higher and Poetry 1.8.5 or higher. | ||
| You can run the following commands in your terminal to check your local Python and Poetry versions: | ||
| ```bash | ||
| python --version | ||
| poetry --version | ||
| ``` | ||
| If the versions are not correct or you don't have Python or Poetry installed, download and follow their setup instructions: | ||
| * Python: install with [pyenv](https://github.com/pyenv/pyenv) | ||
| * Poetry: follow the official [Poetry installation instructions](https://python-poetry.org/docs/#installation) | ||
| **Note**: You will also need to have Rust and Cargo installed. Follow the official [Rust installation instructions](https://doc.rust-lang.org/cargo/getting-started/installation.html) | ||
| ## Adding an Agentic Action | ||
| One of the most common ways to contribute to AgentKit is by adding a new agentic action. Here are the high level steps: | ||
| **Note: It is recommended to point your editor to the specific package that you are working in. This will help ensure things like package imports are working correctly** | ||
| 1. Create a new file in `cdp-agentkit-core/python/cdp_agentkit_core/actions` | ||
| 2. Implement your new action inside your newly created file | ||
| - For an example of an action, see [mint_nft.py](./cdp-agentkit-core/python/cdp_agentkit_core/actions/mint_nft.py) | ||
| 3. Add your action to [__init__.py](./cdp-agentkit-core/python/cdp_agentkit_core/actions/__init__.py) | ||
| 4. Add a test for your action in `cdp-agentkit-core/python/tests/actions` | ||
| - For an example, see [test_mint_nft.py](./cdp-agentkit-core/python/tests/actions/test_mint_nft.py) | ||
| Actions are created by implementing the `CdpAction` interface: | ||
| ```python | ||
| from collections.abc import Callable | ||
| from cdp import Wallet | ||
| from pydantic import BaseModel, Field | ||
| from cdp_agentkit_core.actions import CdpAction | ||
| 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. | ||
| """ | ||
| 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`", | ||
| ) | ||
| 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"} | ||
| try: | ||
| mint_invocation = wallet.invoke_contract( | ||
| contract_address=contract_address, method="mint", args=mint_args | ||
| ).wait() | ||
| except Exception as e: | ||
| return f"Error minting NFT {e!s}" | ||
| 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}" | ||
| class MintNftAction(CdpAction): | ||
| """Mint NFT action.""" | ||
| name: str = "mint_nft" | ||
| description: str = MINT_NFT_PROMPT | ||
| args_schema: type[BaseModel] | None = MintNftInput | ||
| func: Callable[..., str] = mint_nft | ||
| ``` | ||
| #### Components of an Agentic Action | ||
| 1. **Input Schema**: Define the input parameters using Pydantic schemas | ||
| 2. **Prompt**: A description that helps the AI understand when and how to use the action. It's important to describe the inputs and outputs of the action and include examples. Additionally, think about what inputs can be removed entirely and fetched or inferred by the LLM, so that users don't have to manually provide them. | ||
| 3. **Action Class**: Implements the `CdpAction` interface with: | ||
| - `name`: Unique identifier for the action | ||
| - `description`: The prompt text | ||
| - `args_schema`: The Pydantic schema for validating inputs | ||
| - `func`: The implementation function | ||
| 4. **Implementation Function**: The actual logic that executes the action | ||
| Check out the [Testing](#testing) section to learn how to manually test your new action. | ||
| ## Adding an Agentic Action to Langchain Toolkit | ||
| The action will be included automatically, all you need to do is add the action to the list of tools in the `CdpToolkit` class documentation in `cdp-langchain/python/cdp_langchain/agent_toolkits/cdp_toolkit.py`. | ||
| ## Adding an Agentic Action to the Twitter Toolkit | ||
| 1. Ensure the action is implemented in `cdp-agentkit-core/actions/social/twitter`. | ||
| 2. Add a wrapper method to `TwitterApiWrapper` in `./twitter_langchain/twitter_api_wrapper.py` | ||
| - E.g. | ||
| ```python | ||
| 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) | ||
| ``` | ||
| 3. Add call to the wrapper in `TwitterApiWrapper.run` in `./twitter_langchain/twitter_api_wrapper.py` | ||
| - E.g. | ||
| ```python | ||
| if mode == "post_tweet": | ||
| return self.post_tweet_wrapper(**kwargs) | ||
| ``` | ||
| 4. Add the action to the list of available tools in the `TwitterToolkit` in `./twitter_langchain/twitter_toolkit.py` | ||
| - E.g. | ||
| ```python | ||
| actions: List[Dict] = [ | ||
| { | ||
| "mode": "post_tweet", | ||
| "name": "post_tweet", | ||
| "description": POST_TWEET_PROMPT, | ||
| "args_schema": PostTweetInput, | ||
| }, | ||
| ] | ||
| ``` | ||
| 5. Update `TwitterToolkit` documentation | ||
| - Add the action to the list of tools | ||
| - Add any additional ENV requirements | ||
| ## Testing | ||
| ### Local Testing | ||
| A good way to test new actions locally is by using the chatbot example in `cdp-langchain`. This requires a couple API keys: | ||
| - Get a Coinbase Developer Platform API Key from the [CDP Portal](https://portal.cdp.coinbase.com/access/api) | ||
| - Get an [OpenAI API Key](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key) | ||
| The flow is: | ||
| 1. Make your change as described in the [Adding an Agentic Action](#adding-an-agentic-action) section | ||
| 2. Update `cdp-langchain/examples/chatbot-python/pyproject.toml` to point to the local package | ||
| ```diff | ||
| [tool.poetry] | ||
| name = "chatbot-python" | ||
| version = "0.0.1" | ||
| description = "CDP AgentKit Example Chatbot" | ||
| authors = ["John Peterson <john.peterson@coinbase.com>"] | ||
| readme = "README.md" | ||
| package-mode = false | ||
| [tool.poetry.dependencies] | ||
| python = "^3.10" | ||
| - cdp-langchain = "^0.0.11" | ||
| + cdp-langchain = { path: "../../cdp-agentkit-core/python", develop: true } | ||
| [build-system] | ||
| requires = ["poetry-core"] | ||
| build-backend = "poetry.core.masonry.api" | ||
| ``` | ||
| 3. In `cdp-langchain/examples/chatbot-python`, run `python chatbot.py` | ||
| 4. You can now interact with your new action via the chatbot! | ||
| ### Running Unit Tests | ||
| From the package you are working in, you can run: | ||
| ```bash | ||
| make test | ||
| ``` | ||
| For example, to run all tests in the `cdp_agentkit_core` package, you can run: | ||
| ```bash | ||
| cd cdp-agentkit-core/python | ||
| make test | ||
| ``` | ||
| ## Code Style | ||
| We use `ruff` for linting and formatting. Run: | ||
| ```bash | ||
| # Format code | ||
| make format | ||
| # Lint code | ||
| make lint | ||
| # Fix linting issues | ||
| make lint-fix | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| # TypeScript Development Guide | ||
| This guide covers TypeScript-specific setup and development for AgentKit. | ||
| ## Contents | ||
| - [Development Setup](#development-setup) | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. May not be appropriate for this pass, but at some point it would be great to define how we want contributors to integrate AgentKit into new frameworks. Some of the prizes for the SF AI hackathon reward for this. Main goal being to prevent a framework user from having to do anything but import the latest package for agentkit to get all of the most recent features and capabilities | ||
| - [Adding an Agentic Action](#adding-an-agentic-action) | ||
| - [Adding an Agentic Action to Langchain Toolkit](#adding-an-agentic-action-to-langchain-toolkit) | ||
| - [Testing](#testing) | ||
| - [Code Style](#code-style) | ||
| ## Development Setup | ||
| AgentKit uses Node.js v23.4.0 or higher and npm 10.9.2 or higher. | ||
| You can run the following commands in your terminal to check your local Node.js and npm versions: | ||
| ```bash | ||
| node --version | ||
| npm --version | ||
| ``` | ||
| If the versions are not correct or you don't have Node.js or npm installed, download through [nvm](https://github.com/nvm-sh/nvm). | ||
| ## Adding an Agentic Action | ||
| One of the most common ways to contribute to AgentKit is by adding a new agentic action. Here are the high level steps: | ||
| **Note: It is recommended to point your editor to the specific package that you are working in. This will help ensure things like package imports are working correctly** | ||
| 1. Create a new file in `cdp-agentkit-core/typescript/src/actions/cdp` | ||
| 2. Implement your new action inside your newly created file | ||
| - For an example of an action, see [mint_nft.py](./cdp-agentkit-core/typescript/src/actions/cdp/mint_nft.ts) | ||
0xRAG marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| 3. Add your action to [index.ts](./cdp-agentkit-core/typescript/src/actions/cdp/index.ts) | ||
| 4. Add a test for your action in `cdp-agentkit-core/typescript/src/tests` | ||
| - For an example, see [mint_nft_test.ts](./cdp-agentkit-core/typescript/src/tests/mint_nft_test.ts) | ||
| Actions are created by implementing the `CdpAction` interface: | ||
| ```typescript | ||
| 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; | ||
| } | ||
| ``` | ||
| #### Components of an Agentic Action | ||
| 1. **Input Schema**: Define the input parameters using Zod schemas | ||
| 2. **Prompt**: A description that helps the AI understand when and how to use the action. It's important to describe the inputs and outputs of the action and include examples. Additionally, think about what inputs can be removed entirely and fetched or inferred by the LLM, so that users don't have to manually provide them. | ||
| 3. **Action Class**: Implements the `CdpAction` interface with: | ||
| - `name`: Unique identifier for the action | ||
| - `description`: The prompt text | ||
| - `argsSchema`: The Zod schema for validating inputs | ||
| - `func`: The implementation function | ||
| 4. **Implementation Function**: The actual logic that executes the action | ||
| Check out the [Testing](#testing) section to learn how to manually test your new action. | ||
| ## Adding an Agentic Action to Langchain Toolkit | ||
| The action will be included automatically, all you need to do is add the action to the list of tools in the `CdpToolkit` class documentation in `cdp-langchain/typescript/src/toolkits/cdp_toolkit.ts`. | ||
| ## Testing | ||
| ### Local Testing | ||
| A good way to test new actions locally is by using the chatbot example in `cdp-langchain`. This requires a couple API keys: | ||
| - Get a Coinbase Developer Platform API Key from the [CDP Portal](https://portal.cdp.coinbase.com/access/api) | ||
| - Get an [OpenAI API Key](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key) | ||
| The flow is: | ||
| 1. Make your change as described in the [Adding an Agentic Action](#adding-an-agentic-action) section | ||
| 2. Re-build the package by running `npm run build` (either from root, or from the package folder will do) | ||
| 3. In `cdp-langchain/examples/chatbot-typescript`, run `npm run start` | ||
0xRAG marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| 4. You can now interact with your new action via the chatbot! | ||
| ### Running Tests | ||
| From the package you are working in, you can run: | ||
| ```bash | ||
| npm test | ||
| ``` | ||
| For example, to run all tests in the `cdp-agentkit-core` package, you can run: | ||
| ```bash | ||
| cd cdp-agentkit-core/typescript | ||
| npm test | ||
| ``` | ||
| ## Code Style | ||
| We use ESLint and Prettier for linting and formatting. Run: | ||
| ```bash | ||
| # Format code | ||
| npm run format | ||
| # Lint code | ||
| npm run lint | ||
| # Fix linting issues | ||
| npm run lint:fix | ||
| ``` | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thoughts about putting a context section here or some sort of link out to CDP SDK for those using contract invocations? Want to prevent issues where someone uses an API or something that is an unnecessary dependency/requires each user to provision API keys (where possible. If there's no other option that's fine but we can't include it as a default tool)