Skip to content

Commit 3c2682b

Browse files
chore: Remove Action enumeration/re-implementation in Framework Exts (coinbase#25)
1 parent 69438c3 commit 3c2682b

26 files changed

+378
-656
lines changed

CONTRIBUTING.md

Lines changed: 18 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,27 @@ git clone git@github.com:coinbase/cdp-agentkit.git
2525

2626
## Adding an Action to Agentkit Core
2727
- Actions are defined in `./cdp_agentkit_core/actions` module. See `./cdp_agentkit_core/actions/mint_nft.py` for an example.
28+
- Actions are created by subclassing `CdpAction`
29+
E.g.
30+
```python
31+
class DeployNftAction(CdpAction):
32+
"""Deploy NFT action."""
33+
34+
name: str = "mint_nft"
35+
description: str = MINT_NFT_PROMPT
36+
args_schema: type[BaseModel] | None = MintNftInput
37+
func: Callable[..., str] = mint_nft
38+
```
2839

2940
### Components of an Agentic Action
30-
Each action will define and export 3 components:
31-
- Prompt - A string that will provide the AI Agent with context on what the function does and a natural language description of the input.
41+
- `name` - Name of the action.
42+
- `description` - A string that will provide the AI Agent with context on what the function does and a natural language description of the input.
3243
- E.g.
3344
```python
3445
MINT_NFT_PROMPT = """
3546
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."""
3647
```
37-
- ArgSchema - A Pydantic Model that defines the input argument schema for the action.
48+
- `arg_schema` - A Pydantic Model that defines the input argument schema for the action.
3849
- E.g.
3950
```python
4051
class MintNftInput(BaseModel):
@@ -49,7 +60,7 @@ class MintNftInput(BaseModel):
4960
description="The destination address that will receieve the NFT onchain, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`",
5061
)
5162
```
52-
- Action Callable - A function (or Callable class) that executes the action.
63+
- `func` - A function (or Callable class) that executes the action.
5364
- E.g.
5465
```python
5566
def mint_nft(wallet: Wallet, contract_address: str, destination: str) -> str:
@@ -74,47 +85,9 @@ def mint_nft(wallet: Wallet, contract_address: str, destination: str) -> str:
7485
```
7586

7687
## Adding an Agentic Action to Langchain Toolkit
77-
1. Ensure the action is implemented in `cdp-agentkit-core`.
78-
2. Add a wrapper method to `CdpAgentkitWrapper` in `./cdp_langchain/utils/cdp_agentkit_wrapper.py`
79-
- E.g.
80-
```python
81-
def mint_nft_wrapper(self, contract_address: str, destination: str) -> str:
82-
"""Mint an NFT (ERC-721) to a specified destination address onchain via a contract invocation.
83-
84-
Args:
85-
contract_address (str): "The contract address of the NFT (ERC-721) to mint, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`".
86-
destination (str): "The destination address that will receieve the NFT onchain, e.g. `0x036CbD53842c5426634e7929541eC2318f3dCF7e`".
87-
88-
Returns:
89-
str: A message containing the NFT mint details.
90-
91-
"""
92-
return mint_nft(
93-
wallet=self.wallet,
94-
contract_address=contract_address,
95-
destination=destination,
96-
)
97-
```
98-
3. Add call to the wrapper in `CdpAgentkitWrapper.run` in `./cdp_langchain/utils/cdp_agentkit_wrapper.py`
99-
- E.g.
100-
```python
101-
if mode == "mint_nft":
102-
return self.mint_nft_wrapper(**kwargs)
103-
104-
```
105-
4. Add the action to the list of available tools in the `CdpToolkit` in `./cdp_langchain/agent_toolkits/cdp_toolkit.py`
106-
- E.g.
107-
```python
108-
actions: List[Dict] = [
109-
{
110-
"mode": "mint_nft",
111-
"name": "mint_nft",
112-
"description": MINT_NFT_PROMPT,
113-
"args_schema": MintNftInput,
114-
},
115-
]
116-
```
117-
5. Add the action to the list of tools in the `CdpToolkit` class documentation.
88+
1. Ensure the action is implemented in `cdp-agentkit-core` and in a released version.
89+
2. Update the `cdp-agentkit-core` dependency to the latest version.
90+
3. Add the action to the list of tools in the `CdpToolkit` class documentation.
11891

11992
## Adding an Agentic Action to the Twitter Toolkit
12093
1. Ensure the action is implemented in `cdp-agentkit-core/actions/social/twitter`.
Lines changed: 34 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,37 @@
1-
from cdp_agentkit_core.actions.deploy_nft import (
2-
DEPLOY_NFT_PROMPT,
3-
DeployNftInput,
4-
deploy_nft,
5-
)
6-
from cdp_agentkit_core.actions.deploy_token import (
7-
DEPLOY_TOKEN_PROMPT,
8-
DeployTokenInput,
9-
deploy_token,
10-
)
11-
from cdp_agentkit_core.actions.get_balance import (
12-
GET_BALANCE_PROMPT,
13-
GetBalanceInput,
14-
get_balance,
15-
)
16-
from cdp_agentkit_core.actions.get_wallet_details import (
17-
GET_WALLET_DETAILS_PROMPT,
18-
GetWalletDetailsInput,
19-
get_wallet_details,
20-
)
21-
from cdp_agentkit_core.actions.mint_nft import (
22-
MINT_NFT_PROMPT,
23-
MintNftInput,
24-
mint_nft,
25-
)
26-
from cdp_agentkit_core.actions.register_basename import (
27-
REGISTER_BASENAME_PROMPT,
28-
RegisterBasenameInput,
29-
register_basename,
30-
)
31-
from cdp_agentkit_core.actions.request_faucet_funds import (
32-
REQUEST_FAUCET_FUNDS_PROMPT,
33-
RequestFaucetFundsInput,
34-
request_faucet_funds,
35-
)
36-
from cdp_agentkit_core.actions.trade import (
37-
TRADE_PROMPT,
38-
TradeInput,
39-
trade,
40-
)
41-
from cdp_agentkit_core.actions.transfer import (
42-
TRANSFER_PROMPT,
43-
TransferInput,
44-
transfer,
45-
)
46-
from cdp_agentkit_core.actions.uniswap_v3.create_pool import (
47-
UNISWAP_V3_CREATE_POOL_PROMPT,
48-
UniswapV3CreatePoolInput,
49-
uniswap_v3_create_pool,
50-
)
1+
from cdp_agentkit_core.actions.cdp_action import CdpAction
2+
from cdp_agentkit_core.actions.deploy_nft import DeployNftAction
3+
from cdp_agentkit_core.actions.deploy_token import DeployTokenAction
4+
from cdp_agentkit_core.actions.get_balance import GetBalanceAction
5+
from cdp_agentkit_core.actions.get_wallet_details import GetWalletDetailsAction
6+
from cdp_agentkit_core.actions.mint_nft import MintNftAction
7+
from cdp_agentkit_core.actions.register_basename import RegisterBasenameAction
8+
from cdp_agentkit_core.actions.request_faucet_funds import RequestFaucetFundsAction
9+
from cdp_agentkit_core.actions.trade import TradeAction
10+
from cdp_agentkit_core.actions.transfer import TransferAction
11+
from cdp_agentkit_core.actions.uniswap_v3.create_pool import UniswapV3CreatePoolAction
12+
13+
14+
def get_all_cdp_actions() -> list[type[CdpAction]]:
15+
"""Retrieve all subclasses of CdpAction defined in the package."""
16+
actions = []
17+
for action in CdpAction.__subclasses__():
18+
actions.append(action())
19+
return actions
20+
21+
22+
CDP_ACTIONS = get_all_cdp_actions()
5123

5224
__all__ = [
53-
"UNISWAP_V3_CREATE_POOL_PROMPT",
54-
"UniswapV3CreatePoolInput",
55-
"uniswap_v3_create_pool",
56-
"DEPLOY_NFT_PROMPT",
57-
"DeployNftInput",
58-
"deploy_nft",
59-
"DEPLOY_TOKEN_PROMPT",
60-
"DeployTokenInput",
61-
"deploy_token",
62-
"GET_BALANCE_PROMPT",
63-
"GetBalanceInput",
64-
"get_balance",
65-
"GET_WALLET_DETAILS_PROMPT",
66-
"GetWalletDetailsInput",
67-
"get_wallet_details",
68-
"MINT_NFT_PROMPT",
69-
"MintNftInput",
70-
"mint_nft",
71-
"REGISTER_BASENAME_PROMPT",
72-
"RegisterBasenameInput",
73-
"register_basename",
74-
"REQUEST_FAUCET_FUNDS_PROMPT",
75-
"RequestFaucetFundsInput",
76-
"request_faucet_funds",
77-
"TRADE_PROMPT",
78-
"TradeInput",
79-
"trade",
80-
"TRANSFER_PROMPT",
81-
"TransferInput",
82-
"transfer",
25+
"CdpAction",
26+
"GetWalletDetailsAction",
27+
"DeployNftAction",
28+
"DeployTokenAction",
29+
"GetBalanceAction",
30+
"MintNftAction",
31+
"RegisterBasenameAction",
32+
"RequestFaucetFundsAction",
33+
"TradeAction",
34+
"TransferAction",
35+
"UniswapV3CreatePoolAction",
36+
"CDP_ACTIONS",
8337
]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from collections.abc import Callable
2+
3+
from pydantic import BaseModel
4+
5+
6+
class CdpAction(BaseModel):
7+
"""CDP Action Base Class."""
8+
9+
name: str
10+
description: str
11+
args_schema: type[BaseModel] | None = None
12+
func: Callable[..., str]

cdp-agentkit-core/cdp_agentkit_core/actions/deploy_nft.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
from collections.abc import Callable
2+
13
from cdp import Wallet
24
from pydantic import BaseModel, Field
35

6+
from cdp_agentkit_core.actions import CdpAction
7+
48
DEPLOY_NFT_PROMPT = """
59
This tool will deploy an NFT (ERC-721) contract onchain from the wallet. It takes the name of the NFT collection, the symbol of the NFT collection, and the base URI for the token metadata as inputs."""
610

@@ -38,3 +42,12 @@ def deploy_nft(wallet: Wallet, name: str, symbol: str, base_uri: str) -> str:
3842
nft_contract = wallet.deploy_nft(name=name, symbol=symbol, base_uri=base_uri).wait()
3943

4044
return f"Deployed NFT Collection {name} to address {nft_contract.contract_address} on network {wallet.network_id}.\nTransaction hash for the deployment: {nft_contract.transaction.transaction_hash}\nTransaction link for the deployment: {nft_contract.transaction.transaction_link}"
45+
46+
47+
class DeployNftAction(CdpAction):
48+
"""Deploy NFT action."""
49+
50+
name: str = "deploy_nft"
51+
description: str = DEPLOY_NFT_PROMPT
52+
args_schema: type[BaseModel] | None = DeployNftInput
53+
func: Callable[..., str] = deploy_nft

cdp-agentkit-core/cdp_agentkit_core/actions/deploy_token.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
from collections.abc import Callable
2+
13
from cdp import Wallet
24
from pydantic import BaseModel, Field
35

6+
from cdp_agentkit_core.actions import CdpAction
7+
48
DEPLOY_TOKEN_PROMPT = """
59
This tool will deploy an ERC20 token smart contract. It takes the token name, symbol, and total supply as input. The token will be deployed using the wallet's default address as the owner and initial token holder.
610
"""
@@ -34,3 +38,12 @@ def deploy_token(wallet: Wallet, name: str, symbol: str, total_supply: str) -> s
3438
token_contract.wait()
3539

3640
return f"Deployed ERC20 token contract {name} ({symbol}) with total supply of {total_supply} tokens at address {token_contract.contract_address}. Transaction link: {token_contract.transaction.transaction_link}"
41+
42+
43+
class DeployTokenAction(CdpAction):
44+
"""Deploy token action."""
45+
46+
name: str = "deploy_token"
47+
description: str = DEPLOY_TOKEN_PROMPT
48+
args_schema: type[BaseModel] | None = DeployTokenInput
49+
func: Callable[..., str] = deploy_token

cdp-agentkit-core/cdp_agentkit_core/actions/get_balance.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
from collections.abc import Callable
2+
13
from cdp import Wallet
24
from pydantic import BaseModel, Field
35

6+
from cdp_agentkit_core.actions import CdpAction
7+
48
GET_BALANCE_PROMPT = """
59
This tool will get the balance of all the addresses in the wallet for a given asset. It takes the asset ID as input."""
610

@@ -35,3 +39,12 @@ def get_balance(wallet: Wallet, asset_id: str) -> str:
3539
balance_lines = [f" {addr}: {balance}" for addr, balance in balances.items()]
3640
formatted_balances = "\n".join(balance_lines)
3741
return f"Balances for wallet {wallet.id}:\n{formatted_balances}"
42+
43+
44+
class GetBalanceAction(CdpAction):
45+
"""Get wallet balance action."""
46+
47+
name: str = "get_balance"
48+
description: str = GET_BALANCE_PROMPT
49+
args_schema: type[BaseModel] | None = GetBalanceInput
50+
func: Callable[..., str] = get_balance
Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
1+
from collections.abc import Callable
2+
13
from cdp import Wallet
2-
from pydantic import BaseModel, Field
4+
from pydantic import BaseModel
35

4-
GET_WALLET_DETAILS_PROMPT = """
5-
This tool will get details about the MPC Wallet."""
6+
from cdp_agentkit_core.actions import CdpAction
67

78

89
class GetWalletDetailsInput(BaseModel):
910
"""Input argument schema for get wallet details action."""
1011

11-
no_input: str = Field(
12-
"",
13-
description="No input required, e.g. `` (empty string).",
14-
)
15-
1612

1713
def get_wallet_details(wallet: Wallet) -> str:
1814
"""Get a wallet's details.
@@ -25,3 +21,12 @@ def get_wallet_details(wallet: Wallet) -> str:
2521
2622
"""
2723
return f"Wallet: {wallet.id} on network: {wallet.network_id} with default address: {wallet.default_address.address_id}"
24+
25+
26+
class GetWalletDetailsAction(CdpAction):
27+
"""Get wallet details action."""
28+
29+
name: str = "get_wallet_details"
30+
description: str = "This tool will get details about the MPC Wallet."
31+
args_schema: type[BaseModel] | None = GetWalletDetailsInput
32+
func: Callable[..., str] = get_wallet_details

cdp-agentkit-core/cdp_agentkit_core/actions/mint_nft.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
from collections.abc import Callable
2+
13
from cdp import Wallet
24
from pydantic import BaseModel, Field
35

6+
from cdp_agentkit_core.actions import CdpAction
7+
48
MINT_NFT_PROMPT = """
59
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."""
610

@@ -37,3 +41,12 @@ def mint_nft(wallet: Wallet, contract_address: str, destination: str) -> str:
3741
).wait()
3842

3943
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}"
44+
45+
46+
class MintNftAction(CdpAction):
47+
"""Mint NFT action."""
48+
49+
name: str = "mint_nft"
50+
description: str = MINT_NFT_PROMPT
51+
args_schema: type[BaseModel] | None = MintNftInput
52+
func: Callable[..., str] = mint_nft

cdp-agentkit-core/cdp_agentkit_core/actions/register_basename.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
from collections.abc import Callable
2+
13
from cdp import Wallet
24
from pydantic import BaseModel, Field
35
from web3 import Web3
46
from web3.exceptions import ContractLogicError
57

8+
from cdp_agentkit_core.actions import CdpAction
9+
610
# Constants
711
REGISTER_BASENAME_PROMPT = """
812
This tool will register a Basename for the agent. The agent should have a wallet associated to register a Basename.
@@ -30,13 +34,13 @@ class RegisterBasenameInput(BaseModel):
3034
)
3135

3236

33-
def register_basename(wallet: Wallet, basename: str, amount: float | None = 0.002) -> str:
37+
def register_basename(wallet: Wallet, basename: str, amount: str = "0.002") -> str:
3438
"""Register a Basename for the agent.
3539
3640
Args:
3741
wallet (Wallet): The wallet to register the Basename with.
3842
basename (str): The Basename to assign to the agent.
39-
amount (float): The amount of ETH to pay for the registration. The default is set to 0.002.
43+
amount (str): The amount of ETH to pay for the registration. The default is set to 0.002.
4044
4145
Returns:
4246
str: Confirmation message with the basename.
@@ -158,3 +162,12 @@ def create_register_contract_method_args(base_name: str, address_id: str, is_mai
158162
"type": "function",
159163
}
160164
]
165+
166+
167+
class RegisterBasenameAction(CdpAction):
168+
"""Register Basename action."""
169+
170+
name: str = "register_basename"
171+
description: str = REGISTER_BASENAME_PROMPT
172+
args_schema: type[BaseModel] | None = RegisterBasenameInput
173+
func: Callable[..., str] = register_basename

0 commit comments

Comments
 (0)