diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d199918a5..f7e0dc5f5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,19 @@ # CDP Agentkit Contributing Guide +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 ## Development -### Python Version +### Prerequisites +- Python 3.10 or higher +- Rust/Cargo installed ([Rust Installation Instructions](https://doc.rust-lang.org/cargo/getting-started/installation.html)) +- Poetry for package management and tooling + - [Poetry Installation Instructions](https://python-poetry.org/docs/#installation) -Developing in this repository requires Python 3.10 or higher. +`cdp-langchain` also requires a [CDP API Key](https://portal.cdp.coinbase.com/access/api). ### Set-up @@ -13,3 +22,114 @@ Clone the repo by running: ```bash git clone git@github.com:coinbase/cdp-agentkit.git ``` + +## Adding an Action to Agentkit Core +- Actions are defined in `./cdp_agentkit_core/actions` module. See `./cdp_agentkit_core/actions/mint_nft.py` for an example. + +### Components of an Agentic Action +Each action will define and export 3 components: +- Prompt - 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. +```python +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.""" +``` +- ArgSchema - A Pydantic Model that defines the input argument schema for the action. + - E.g. +```python +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 receieve the NFT onchain, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`", + ) +``` +- Action Callable - A function (or Callable class) that executes the action. + - E.g. +```python +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 receieve 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}" +``` + +## Adding an Agentic Action to Langchain Toolkit +1. Ensure the action is implemented in `cdp-agentkit-core`. +2. Add a wrapper method to `CdpAgentkitWrapper` in `./cdp_langchain/utils/cdp_agentkit_wrapper.py` + - E.g. +```python + def mint_nft_wrapper(self, contract_address: str, destination: str) -> str: + """Mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation. + + Args: + contract_address (str): "The contract address of the NFT (ERC-721) to mint, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`". + destination (str): "The destination address that will receieve the NFT onchain, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`". + + Returns: + str: A message containing the NFT mint details. + + """ + return mint_nft( + wallet=self.wallet, + contract_address=contract_address, + destination=destination, + ) +``` +3. Add call to the wrapper in `CdpAgentkitWrapper.run` in `./cdp_langchain/utils/cdp_agentkit_wrapper.py` + - E.g. +```python + if mode == "mint_nft": + return self.mint_nft_wrapper(**kwargs) + +``` +4. Add the action to the list of available tools in the `CdpToolkit` in `./cdp_langchain/agent_toolkits/cdp_toolkit.py` + - E.g. +```python + actions: List[Dict] = [ + { + "mode": "mint_nft", + "name": "mint_nft", + "description": MINT_NFT_PROMPT, + "args_schema": MintNftInput, + }, + ] +``` +5. Add the action to the list of tools in the `CdpToolkit` class documentation. + +## Development Tools +### Formatting +`make format` + +### Linting +- Check linter +`make lint` + +- Fix linter errors +`make lint-fix` + +### Unit Testing +- Run unit tests +`make test` + +## Changelog +- 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. \ No newline at end of file diff --git a/README.md b/README.md index 6e03ce0a4..b20e05cd1 100644 --- a/README.md +++ b/README.md @@ -5,16 +5,22 @@ [![GitHub star chart](https://img.shields.io/github/stars/coinbase/cdp-agentkit?style=flat-square)](https://star-history.com/#coinbase/cdp-agentkit) [![Open Issues](https://img.shields.io/github/issues-raw/coinbase/cdp-agentkit?style=flat-square)](https://github.com/coinbase/cdp-agentkit/issues) -The Coinbase Developer Platform (CDP) Agentkit simplifies bringing your AI Agents onchain! - -Agentkit is powered by the [CDP SDK](https://github.com/coinbase/cdp-sdk-python) - -Every AI Agent deserves a Wallet! +The Coinbase Developer Platform (CDP) Agentkit simplifies bringing your AI Agents onchain. Every AI Agent deserves a crypto wallet! + +## Key Features +- Framework-agnostic: Common AI Agent primitives that can be used with any AI framework. +- Langchain Toolkit: Integration with Langchain for easy agentic workflows. More frameworks coming soon! +- Support for various on-chain actions: + - Faucet for testnet funds + - Getting wallet details and balances + - Transferring and trading tokens + - Registering Basenames + - Deploying ERC20 tokens and creating uniswap_v3 pools for trading + - Deploying ERC721 tokens and minting NFTs ## Examples -Check out `cdp-langchain/examples` for inspiration and help getting started! Learn more about each one in its README. - -- [Chatbot](./cdp-langchain/examples/chatbot/README.md): Simple example of a Chatbot that can perform complex onchain interactions. +Check out `cdp-langchain/examples` for inspiration and help getting started! +- [Chatbot](./cdp-langchain/examples/chatbot/README.md): Simple example of a Chatbot that can perform complex onchain interactions, using OpenAI. ## Repository Structure CDP Agentkit is organized as a [monorepo](https://en.wikipedia.org/wiki/Monorepo) that contains multiple packages. @@ -23,13 +29,14 @@ CDP Agentkit is organized as a [monorepo](https://en.wikipedia.org/wiki/Monorepo Core primitives and framework agnostic tools that are meant to be composable and used via CDP Agentkit framework extensions. See [CDP Agentkit Core](./cdp-agentkit-core/README.md) to get started! -### CDP Agentkit Extensions -CDP Agentkit integrations with popular AI frameworks. - -#### cdp-langchain -Langchain Toolkit extension of CDP Agentkit. +### cdp-langchain +Langchain Toolkit extension of CDP Agentkit. Enables agentic workflows to interact with onchain actions. See [CDP Langchain](./cdp-langchain/README.md) to get started! +### twitter-langchain +Langchain Toolkit extension for Twitter. Enables agentic workflows to interact with Twitter, such as to post a tweet. +See [Twitter Langchain](./twitter-langchain/README.md) to get started! + ## Contributing CDP Agentkit welcomes community contributions. See [CONTRIBUTING.md](CONTRIBUTING.md) for more information. diff --git a/cdp-agentkit-core/README.md b/cdp-agentkit-core/README.md index 872ae9da7..8ee0f2ef7 100644 --- a/cdp-agentkit-core/README.md +++ b/cdp-agentkit-core/README.md @@ -1,78 +1,7 @@ # Agentkit Core -Core primitives and framework agnostic tools that are meant to be composable and used via Agentkit framework extensions. +Framework agnostic primitives that are meant to be composable and used via Agentkit framework extensions. -## Developing -- `cdp-sdk` has a dependency on `cargo`, please install rust and add `cargo` to your path - - [Rust Installation Instructions](https://doc.rust-lang.org/cargo/getting-started/installation.html) - - `export PATH="$HOME/.cargo/bin:$PATH"` -- Agentkit uses `poetry` for package management and tooling - - [Poetry Installation Instructions](https://python-poetry.org/docs/#installation) - - Run `poetry install` to install `cdp-agentkit-core` dependencies - - Run `poetry shell` to activate the virtual environment +You can find all of the supported actions under `./cdp_agentkit_core/actions` -## Documentation -- [Agentkit-Core](https://coinbase.github.io/cdp-agentkit-core) - -### Formatting -`make format` - -### Linting -- Check linter -`make lint` - -- Fix linter errors -`make lint-fix` - -### Unit Testing -- Run unit tests -`make test` - -## Contributing Agentic Actions -- Actions are defined in `./cdp_agentkit_core/actions` module. See `./cdp_agentkit_core/actions/mint_nft.py` for an example. - -### Components of an Agentic Action -Each action will define and export 3 components: -- Prompt - 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. -```python -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.""" -``` -- ArgSchema - A Pydantic Model that defines the input argument schema for the action. - - E.g. -```python -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 receieve the NFT onchain, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`", - ) -``` -- Action Callable - A function (or Callable class) that executes the action. - - E.g. -```python -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 receieve 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}" -``` +## Contributing +See [CONTRIBUTING.md](../CONTRIBUTING.md) for more information. diff --git a/cdp-langchain/README.md b/cdp-langchain/README.md index 50d1c2ad9..cb4371578 100644 --- a/cdp-langchain/README.md +++ b/cdp-langchain/README.md @@ -1,67 +1,120 @@ # CDP Agentkit Extension - Langchain Toolkit +CDP integration with Langchain to enable agentic workflows using the core primitives defined in `cdp-agentkit-core`. -## Developing -- `cdp-sdk` has a dependency on `cargo`, please install rust and add `cargo` to your path - - [Rust Installation Instructions](https://doc.rust-lang.org/cargo/getting-started/installation.html) - - `export PATH="$HOME/.cargo/bin:$PATH"` -- Agentkit uses `poetry` for package management and tooling - - [Poetry Installation Instructions](https://python-poetry.org/docs/#installation) - - Run `poetry install` to install `cdp-langchain` dependencies - - Run `poetry shell` to activate the virtual environment +This toolkit contains tools that enable an LLM agent to interact with the [Coinbase Developer Platform](https://docs.cdp.coinbase.com/). The toolkit provides a wrapper around the CDP SDK, allowing agents to perform onchain operations like transfers, trades, and smart contract interactions. -## Documentation -- [Agentkit-Core](https://coinbase.github.io/cdp-agentkit-core) -- [Agentkit-Langchain](https://coinbase.github.io/cdp-langchain) +## Setup + +### Prerequisites +- Python 3.10 or higher +- [CDP API Key](https://portal.cdp.coinbase.com/access/api) + +### Installation + +```bash +pip install cdp-langchain +``` + +### Environment Setup -### Formatting -`make format` +Set the following environment variables: + +```bash +CDP_API_KEY_NAME= +CDP_API_KEY_PRIVATE_KEY= +OPENAI_API_KEY= +NETWORK_ID=base-sepolia # Optional: Defaults to base-sepolia +``` -### Linting -- Check linter -`make lint` +## Usage -- Fix linter errors -`make lint-fix` +### Basic Setup -## Adding an Agentic Action to the Langchain Toolkit -1. Ensure the action is implemented in `cdp-agentkit-core`. -2. Add a wrapper method to `CdpAgentkitWrapper` in `./cdp_langchain/utils/cdp_agentkit_wrapper.py` - - E.g. ```python - def mint_nft_wrapper(self, contract_address: str, destination: str) -> str: - """Mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation. - - Args: - contract_address (str): "The contract address of the NFT (ERC-721) to mint, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`". - destination (str): "The destination address that will receieve the NFT onchain, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`". - - Returns: - str: A message containing the NFT mint details. - - """ - return mint_nft( - wallet=self.wallet, - contract_address=contract_address, - destination=destination, - ) +from cdp_langchain.agent_toolkits import CdpToolkit +from cdp_langchain.utils import CdpAgentkitWrapper + +# Initialize CDP wrapper +cdp = CdpAgentkitWrapper() + +# Create toolkit from wrapper +toolkit = CdpToolkit.from_cdp_agentkit_wrapper(cdp) ``` -3. Add call to the wrapper in `CdpAgentkitWrapper.run` in `./cdp_langchain/utils/cdp_agentkit_wrapper.py` - - E.g. + +View available tools: +```python +tools = toolkit.get_tools() +for tool in tools: + print(tool.name) +``` + +The toolkit provides the following tools: + +1. **get_wallet_details** - Get details about the MPC Wallet +2. **get_balance** - Get balance for specific assets +3. **request_faucet_funds** - Request test tokens from faucet +4. **transfer** - Transfer assets between addresses +5. **trade** - Trade assets (Mainnet only) +6. **deploy_token** - Deploy ERC-20 token contracts +7. **mint_nft** - Mint NFTs from existing contracts +8. **deploy_nft** - Deploy new NFT contracts +9. **register_basename** - Register a basename for the wallet + +### Using with an Agent + ```python - if mode == "mint_nft": - return self.mint_nft_wrapper(**kwargs) +from langchain_openai import ChatOpenAI +from langgraph.prebuilt import create_react_agent + +# Initialize LLM +llm = ChatOpenAI(model="gpt-4o-mini") + +# Get tools and create agent +tools = toolkit.get_tools() +agent_executor = create_react_agent(llm, tools) +# Example usage +events = agent_executor.stream( + {"messages": [("user", "Send 0.005 ETH to john2879.base.eth")]}, + stream_mode="values" +) + +for event in events: + event["messages"][-1].pretty_print() +``` +Expected output: ``` -4. Add the action to the list of available tools in the `CdpToolkit` in `./cdp_langchain/agent_toolkits/cdp_toolkit.py` - - E.g. +Transferred 0.005 of eth to john2879.base.eth. +Transaction hash for the transfer: 0x78c7c2878659a0de216d0764fc87eff0d38b47f3315fa02ba493a83d8e782d1e +Transaction link for the transfer: https://sepolia.basescan.org/tx/0x78c7c2878659a0de216d0764fc87eff0d38b47f3315fa02ba493a83d8e782d1 +``` +## CDP Tookit Specific Features + +### Wallet Management +The toolkit maintains an MPC wallet that persists between sessions: + ```python - actions: List[Dict] = [ - { - "mode": "mint_nft", - "name": "mint_nft", - "description": MINT_NFT_PROMPT, - "args_schema": MintNftInput, - }, - ] +# Export wallet data +wallet_data = cdp.export_wallet() + +# Import wallet data +values = {"cdp_wallet_data": wallet_data} +cdp = CdpAgentkitWrapper(**values) ``` -5. Add the action to the list of tools in the `CdpToolkit` class documentation. + +### Network Support +The toolkit supports [multiple networks](https://docs.cdp.coinbase.com/cdp-sdk/docs/networks). + +### Gasless Transactions +The following operations support gasless transactions on Base Mainnet: +- USDC transfers +- EURC transfers +- cbBTC transfers + +## Contributing +See [CONTRIBUTING.md](../CONTRIBUTING.md) for detailed setup instructions and contribution guidelines. + +## Documentation +For detailed documentation of all CDP features and configurations, visit: +- [CDP Documentation](https://docs.cdp.coinbase.com/mpc-wallet/docs/welcome) +- [API Reference](https://api.python.langchain.com/en/latest/agent_toolkits/cdp_langchain.agent_toolkits.cdp_toolkit.CDPToolkit.html) \ No newline at end of file