Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions python/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,6 +34,12 @@ PydanticAI extension of AgentKit. Enables agentic workflows to interact with onc

See [AgentKit PydanticAI](./framework-extensions/pydantic-ai/README.md) to get started!

#### `coinbase-agentkit-autogen`

Microsoft Autogen extension of AgentKit. Enables agentic workflows to interact with onchain actions.

See [AgentKit Autogen](./framework-extensions/autogen/README.md)

### `create-onchain-agent`

A quickstart CLI tool to scaffold out a chatbot using Coinbase AgentKit. Runnable via `pipx run create-onchain-agent`.
Expand Down
8 changes: 8 additions & 0 deletions python/examples/autogen-cdp-chatbot/.env.local
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
# Required
CDP_API_KEY_ID=
CDP_API_KEY_SECRET=
CDP_WALLET_SECRET=
OPENAI_API_KEY=

# Optional with defaults
NETWORK_ID=base-sepolia
29 changes: 29 additions & 0 deletions python/examples/autogen-cdp-chatbot/Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
ifneq (,$(wildcard ./.env))
include .env
endif

export

.PHONY: install
install:
uv sync

.PHONY: run
run:
uv run chatbot.py

.PHONY: format
format:
uv run ruff format .

.PHONY: format-check
format-check:
uv run ruff format . --check

.PHONY: lint
lint:
uv run ruff check .

.PHONY: lint-fix
lint-fix:
uv run ruff check . --fix
50 changes: 50 additions & 0 deletions python/examples/autogen-cdp-chatbot/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
# CDP Agentkit Autogen Extension Examples - Chatbot Python

This example demonstrates an agent setup as a terminal style chatbot using Microsoft Autogen integration with CDP Agentkit actions.

## Ask the chatbot to engage in the Web3 ecosystem!

- "What is the price of BTC?"
- "Request some test tokens from the faucet"
- "What are my CDP account details?"
- "Transfer a portion of your ETH to a random address"
- "Deploy an NFT that will go super viral!"
- "Deploy an ERC-20 token with total supply 1 billion"

## Requirements

- Python 3.10+
- uv for package management and tooling
- [uv Installation Instructions](https://github.com/astral-sh/uv?tab=readme-ov-file#installation)
- [CDP API Key](https://portal.cdp.coinbase.com/access/api)
- [OpenAI API Key](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)

### Checking Python Version

Before using the example, ensure that you have the correct version of Python installed. The example requires Python 3.10 or higher. You can check your Python version by running:

```bash
python --version
uv --version
```

## Installation

```bash
make install
```

## Run the Chatbot

### Env

Rename .env.local to .env and ensure the following var are set:

- "CDP_API_KEY_ID"
- "CDP_API_KEY_SECRET"
- "CDP_WALLET_SECRET" # This is the wallet secret for the wallet you want to use for the chatbot
- "OPENAI_API_KEY"

```bash
make run
```
270 changes: 270 additions & 0 deletions python/examples/autogen-cdp-chatbot/chatbot.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
import asyncio
import json
import os
import time

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import BaseChatMessage, TextMessage
from autogen_core.memory import ListMemory
from autogen_ext.models.openai import OpenAIChatCompletionClient
from coinbase_agentkit import (
AgentKit,
AgentKitConfig,
CdpEvmWalletProvider,
CdpEvmWalletProviderConfig,
cdp_api_action_provider,
erc20_action_provider,
pyth_action_provider,
wallet_action_provider,
weth_action_provider,
x402_action_provider,
)
from coinbase_agentkit_autogen.autogen_tools import get_autogen_tools
from dotenv import load_dotenv


def initialize_agent(
config: CdpEvmWalletProviderConfig,
) -> tuple[AssistantAgent, CdpEvmWalletProvider]:
"""Initialize the agent with CDP Agentkit.

Args:
config: Configuration for the CDP EVM Server Wallet Provider

Returns:
tuple[Agent, CdpEvmServerWalletProvider]: The initialized agent and wallet provider

"""
# Initialize the language model
model_client = OpenAIChatCompletionClient(
model="gpt-4o-mini",
)

# Initialize the wallet provider with the config
wallet_provider = CdpEvmWalletProvider(
CdpEvmWalletProviderConfig(
api_key_id=config.api_key_id, # CDP API Key ID
api_key_secret=config.api_key_secret, # CDP API Key Secret
wallet_secret=config.wallet_secret, # CDP Wallet Secret
network_id=config.network_id, # Network ID - Optional, will default to 'base-sepolia'
address=config.address, # Wallet Address - Optional, will trigger idempotency flow if not provided
idempotency_key=config.idempotency_key, # Idempotency Key - Optional, seeds generation of a new wallet
rpc_url=config.rpc_url, # Optional RPC URL override
)
)

# Create AgentKit instance with wallet and action providers
agentkit = AgentKit(
AgentKitConfig(
wallet_provider=wallet_provider,
action_providers=[
cdp_api_action_provider(),
erc20_action_provider(),
pyth_action_provider(),
wallet_action_provider(),
weth_action_provider(),
x402_action_provider(),
],
)
)

# Get tools for the agent
tools = get_autogen_tools(agentkit)

# Set up conversation memory
memory = ListMemory()

# Set up Autogen Assistant Agent
agent = AssistantAgent(
name="assistant",
model_client=model_client,
reflect_on_tool_use=True,
tools=tools,
memory=[memory],
max_tool_iterations=3,
system_message=(
"You are a helpful agent that can interact onchain using the Coinbase Developer Platform AgentKit. "
"You are empowered to interact onchain using your tools. If you ever need funds, you can request "
"them from the faucet if you are on network ID 'base-sepolia'. If not, you can provide your wallet "
"details and request funds from the user. Before executing your first action, get the wallet details "
"to see what network you're on. If there is a 5XX (internal) HTTP error code, ask the user to try "
"again later. If someone asks you to do something you can't do with your currently available tools, "
"you must say so, and encourage them to implement it themselves using the CDP SDK + Agentkit, "
"recommend they go to docs.cdp.coinbase.com for more information. Be concise and helpful with your "
"responses. Refrain from restating your tools' descriptions unless it is explicitly requested."
),
)

# Create and return the agent and wallet provider
return agent, wallet_provider


def setup() -> AssistantAgent:
"""Set up the agent with persistent wallet storage.

Returns:
AssistantAgent: The initialized agent used for handling wallet interactions and
executing associated operations.

"""
# Configure network and file path
network_id = os.getenv("NETWORK_ID", "base-sepolia")
wallet_file = f"wallet_data_{network_id.replace('-', '_')}.txt"

# Load existing wallet data if available
wallet_data = {}
if os.path.exists(wallet_file):
try:
with open(wallet_file) as f:
wallet_data = json.load(f)
print(f"Loading existing wallet from {wallet_file}")
except json.JSONDecodeError:
print(f"Warning: Invalid wallet data for {network_id}")
wallet_data = {}

# Determine wallet address using priority order
wallet_address = (
wallet_data.get("address") # First priority: Saved wallet file
or os.getenv("ADDRESS") # Second priority: ADDRESS env var
or None # Will trigger idempotency flow if needed
)

# Create the wallet provider config
config = CdpEvmWalletProviderConfig(
api_key_id=os.getenv("CDP_API_KEY_ID"),
api_key_secret=os.getenv("CDP_API_KEY_SECRET"),
wallet_secret=os.getenv("CDP_WALLET_SECRET"),
network_id=network_id,
address=wallet_address,
# Only include idempotency_key if we need to create a new wallet
idempotency_key=(os.getenv("IDEMPOTENCY_KEY") if not wallet_address else None),
)

# Initialize the agent and get the wallet provider
agent_executor, wallet_provider = initialize_agent(config)

# Save the wallet data after successful initialization
new_wallet_data = {
"address": wallet_provider.get_address(),
"network_id": network_id,
"created_at": time.strftime("%Y-%m-%d %H:%M:%S")
if not wallet_data
else wallet_data.get("created_at"),
}

with open(wallet_file, "w") as f:
json.dump(new_wallet_data, f, indent=2)
print(f"Wallet data saved to {wallet_file}")

return agent_executor


# Autonomous Mode
async def run_autonomous_mode(agent_executor: AssistantAgent, interval=10) -> None:
"""Run the autonomous mode of the AssistantAgent with a specified interval between actions.

Args:
agent_executor (AssistantAgent): The agent responsible for executing tasks autonomously.
interval (int, optional): Time in seconds to wait between consecutive autonomous actions. Defaults to 10.

"""
print("Starting autonomous mode...")
while True:
try:
# Provide instructions autonomously
thought = (
"Be creative and do something interesting on the blockchain. "
"Choose an action or set of actions and execute it that highlights your abilities."
)

# Run agent in autonomous mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=thought, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

# Wait before the next action
await asyncio.sleep(interval)

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Chat Mode
async def run_chat_mode(agent_executor: AssistantAgent) -> None:
"""Run the assistant agent in chat mode.

Args:
agent_executor (AssistantAgent): The agent executor responsible for handling the
chatbot functionality and running tasks based on user input.

"""
print("Starting chat mode... Type 'exit' to end.")
while True:
try:
user_input = input("\nPrompt: ")
if user_input.lower() == "exit":
break

# Run agent with the user's input in chat mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=user_input, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Mode Selection
def choose_mode():
"""Prompt the user to select a mode of operation from the available options.

Returns
-------
str
The selected mode, either "chat" or "auto".

"""
while True:
print("\nAvailable modes:")
print("1. chat - Interactive chat mode")
print("2. auto - Autonomous action mode")

choice = input("\nChoose a mode (enter number or name): ").lower().strip()
if choice in ["1", "chat"]:
return "chat"
elif choice in ["2", "auto"]:
return "auto"
print("Invalid choice. Please try again.")


async def main():
"""Start the chatbot agent."""
# Load environment variables
load_dotenv()

# Set up the agent
agent_executor = setup()

# Run the agent in the selected mode
mode = choose_mode()
if mode == "chat":
await run_chat_mode(agent_executor=agent_executor)
elif mode == "auto":
await run_autonomous_mode(agent_executor=agent_executor)


if __name__ == "__main__":
print("Starting Agent...")
asyncio.run(main())
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions python/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,6 +34,12 @@ PydanticAI extension of AgentKit. Enables agentic workflows to interact with onc

See [AgentKit PydanticAI](./framework-extensions/pydantic-ai/README.md) to get started!

#### `coinbase-agentkit-autogen`

Microsoft Autogen extension of AgentKit. Enables agentic workflows to interact with onchain actions.

See [AgentKit Autogen](./framework-extensions/autogen/README.md)

### `create-onchain-agent`

A quickstart CLI tool to scaffold out a chatbot using Coinbase AgentKit. Runnable via `pipx run create-onchain-agent`.
Expand Down
8 changes: 8 additions & 0 deletions python/examples/autogen-cdp-chatbot/.env.local
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
# Required
CDP_API_KEY_ID=
CDP_API_KEY_SECRET=
CDP_WALLET_SECRET=
OPENAI_API_KEY=

# Optional with defaults
NETWORK_ID=base-sepolia
29 changes: 29 additions & 0 deletions python/examples/autogen-cdp-chatbot/Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
ifneq (,$(wildcard ./.env))
include .env
endif

export

.PHONY: install
install:
uv sync

.PHONY: run
run:
uv run chatbot.py

.PHONY: format
format:
uv run ruff format .

.PHONY: format-check
format-check:
uv run ruff format . --check

.PHONY: lint
lint:
uv run ruff check .

.PHONY: lint-fix
lint-fix:
uv run ruff check . --fix
50 changes: 50 additions & 0 deletions python/examples/autogen-cdp-chatbot/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
# CDP Agentkit Autogen Extension Examples - Chatbot Python

This example demonstrates an agent setup as a terminal style chatbot using Microsoft Autogen integration with CDP Agentkit actions.

## Ask the chatbot to engage in the Web3 ecosystem!

- "What is the price of BTC?"
- "Request some test tokens from the faucet"
- "What are my CDP account details?"
- "Transfer a portion of your ETH to a random address"
- "Deploy an NFT that will go super viral!"
- "Deploy an ERC-20 token with total supply 1 billion"

## Requirements

- Python 3.10+
- uv for package management and tooling
- [uv Installation Instructions](https://github.com/astral-sh/uv?tab=readme-ov-file#installation)
- [CDP API Key](https://portal.cdp.coinbase.com/access/api)
- [OpenAI API Key](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)

### Checking Python Version

Before using the example, ensure that you have the correct version of Python installed. The example requires Python 3.10 or higher. You can check your Python version by running:

```bash
python --version
uv --version
```

## Installation

```bash
make install
```

## Run the Chatbot

### Env

Rename .env.local to .env and ensure the following var are set:

- "CDP_API_KEY_ID"
- "CDP_API_KEY_SECRET"
- "CDP_WALLET_SECRET" # This is the wallet secret for the wallet you want to use for the chatbot
- "OPENAI_API_KEY"

```bash
make run
```
270 changes: 270 additions & 0 deletions python/examples/autogen-cdp-chatbot/chatbot.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
import asyncio
import json
import os
import time

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import BaseChatMessage, TextMessage
from autogen_core.memory import ListMemory
from autogen_ext.models.openai import OpenAIChatCompletionClient
from coinbase_agentkit import (
AgentKit,
AgentKitConfig,
CdpEvmWalletProvider,
CdpEvmWalletProviderConfig,
cdp_api_action_provider,
erc20_action_provider,
pyth_action_provider,
wallet_action_provider,
weth_action_provider,
x402_action_provider,
)
from coinbase_agentkit_autogen.autogen_tools import get_autogen_tools
from dotenv import load_dotenv


def initialize_agent(
config: CdpEvmWalletProviderConfig,
) -> tuple[AssistantAgent, CdpEvmWalletProvider]:
"""Initialize the agent with CDP Agentkit.

Args:
config: Configuration for the CDP EVM Server Wallet Provider

Returns:
tuple[Agent, CdpEvmServerWalletProvider]: The initialized agent and wallet provider

"""
# Initialize the language model
model_client = OpenAIChatCompletionClient(
model="gpt-4o-mini",
)

# Initialize the wallet provider with the config
wallet_provider = CdpEvmWalletProvider(
CdpEvmWalletProviderConfig(
api_key_id=config.api_key_id, # CDP API Key ID
api_key_secret=config.api_key_secret, # CDP API Key Secret
wallet_secret=config.wallet_secret, # CDP Wallet Secret
network_id=config.network_id, # Network ID - Optional, will default to 'base-sepolia'
address=config.address, # Wallet Address - Optional, will trigger idempotency flow if not provided
idempotency_key=config.idempotency_key, # Idempotency Key - Optional, seeds generation of a new wallet
rpc_url=config.rpc_url, # Optional RPC URL override
)
)

# Create AgentKit instance with wallet and action providers
agentkit = AgentKit(
AgentKitConfig(
wallet_provider=wallet_provider,
action_providers=[
cdp_api_action_provider(),
erc20_action_provider(),
pyth_action_provider(),
wallet_action_provider(),
weth_action_provider(),
x402_action_provider(),
],
)
)

# Get tools for the agent
tools = get_autogen_tools(agentkit)

# Set up conversation memory
memory = ListMemory()

# Set up Autogen Assistant Agent
agent = AssistantAgent(
name="assistant",
model_client=model_client,
reflect_on_tool_use=True,
tools=tools,
memory=[memory],
max_tool_iterations=3,
system_message=(
"You are a helpful agent that can interact onchain using the Coinbase Developer Platform AgentKit. "
"You are empowered to interact onchain using your tools. If you ever need funds, you can request "
"them from the faucet if you are on network ID 'base-sepolia'. If not, you can provide your wallet "
"details and request funds from the user. Before executing your first action, get the wallet details "
"to see what network you're on. If there is a 5XX (internal) HTTP error code, ask the user to try "
"again later. If someone asks you to do something you can't do with your currently available tools, "
"you must say so, and encourage them to implement it themselves using the CDP SDK + Agentkit, "
"recommend they go to docs.cdp.coinbase.com for more information. Be concise and helpful with your "
"responses. Refrain from restating your tools' descriptions unless it is explicitly requested."
),
)

# Create and return the agent and wallet provider
return agent, wallet_provider


def setup() -> AssistantAgent:
"""Set up the agent with persistent wallet storage.

Returns:
AssistantAgent: The initialized agent used for handling wallet interactions and
executing associated operations.

"""
# Configure network and file path
network_id = os.getenv("NETWORK_ID", "base-sepolia")
wallet_file = f"wallet_data_{network_id.replace('-', '_')}.txt"

# Load existing wallet data if available
wallet_data = {}
if os.path.exists(wallet_file):
try:
with open(wallet_file) as f:
wallet_data = json.load(f)
print(f"Loading existing wallet from {wallet_file}")
except json.JSONDecodeError:
print(f"Warning: Invalid wallet data for {network_id}")
wallet_data = {}

# Determine wallet address using priority order
wallet_address = (
wallet_data.get("address") # First priority: Saved wallet file
or os.getenv("ADDRESS") # Second priority: ADDRESS env var
or None # Will trigger idempotency flow if needed
)

# Create the wallet provider config
config = CdpEvmWalletProviderConfig(
api_key_id=os.getenv("CDP_API_KEY_ID"),
api_key_secret=os.getenv("CDP_API_KEY_SECRET"),
wallet_secret=os.getenv("CDP_WALLET_SECRET"),
network_id=network_id,
address=wallet_address,
# Only include idempotency_key if we need to create a new wallet
idempotency_key=(os.getenv("IDEMPOTENCY_KEY") if not wallet_address else None),
)

# Initialize the agent and get the wallet provider
agent_executor, wallet_provider = initialize_agent(config)

# Save the wallet data after successful initialization
new_wallet_data = {
"address": wallet_provider.get_address(),
"network_id": network_id,
"created_at": time.strftime("%Y-%m-%d %H:%M:%S")
if not wallet_data
else wallet_data.get("created_at"),
}

with open(wallet_file, "w") as f:
json.dump(new_wallet_data, f, indent=2)
print(f"Wallet data saved to {wallet_file}")

return agent_executor


# Autonomous Mode
async def run_autonomous_mode(agent_executor: AssistantAgent, interval=10) -> None:
"""Run the autonomous mode of the AssistantAgent with a specified interval between actions.

Args:
agent_executor (AssistantAgent): The agent responsible for executing tasks autonomously.
interval (int, optional): Time in seconds to wait between consecutive autonomous actions. Defaults to 10.

"""
print("Starting autonomous mode...")
while True:
try:
# Provide instructions autonomously
thought = (
"Be creative and do something interesting on the blockchain. "
"Choose an action or set of actions and execute it that highlights your abilities."
)

# Run agent in autonomous mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=thought, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

# Wait before the next action
await asyncio.sleep(interval)

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Chat Mode
async def run_chat_mode(agent_executor: AssistantAgent) -> None:
"""Run the assistant agent in chat mode.

Args:
agent_executor (AssistantAgent): The agent executor responsible for handling the
chatbot functionality and running tasks based on user input.

"""
print("Starting chat mode... Type 'exit' to end.")
while True:
try:
user_input = input("\nPrompt: ")
if user_input.lower() == "exit":
break

# Run agent with the user's input in chat mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=user_input, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Mode Selection
def choose_mode():
"""Prompt the user to select a mode of operation from the available options.

Returns
-------
str
The selected mode, either "chat" or "auto".

"""
while True:
print("\nAvailable modes:")
print("1. chat - Interactive chat mode")
print("2. auto - Autonomous action mode")

choice = input("\nChoose a mode (enter number or name): ").lower().strip()
if choice in ["1", "chat"]:
return "chat"
elif choice in ["2", "auto"]:
return "auto"
print("Invalid choice. Please try again.")


async def main():
"""Start the chatbot agent."""
# Load environment variables
load_dotenv()

# Set up the agent
agent_executor = setup()

# Run the agent in the selected mode
mode = choose_mode()
if mode == "chat":
await run_chat_mode(agent_executor=agent_executor)
elif mode == "auto":
await run_autonomous_mode(agent_executor=agent_executor)


if __name__ == "__main__":
print("Starting Agent...")
asyncio.run(main())
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions python/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,6 +34,12 @@ PydanticAI extension of AgentKit. Enables agentic workflows to interact with onc

See [AgentKit PydanticAI](./framework-extensions/pydantic-ai/README.md) to get started!

#### `coinbase-agentkit-autogen`

Microsoft Autogen extension of AgentKit. Enables agentic workflows to interact with onchain actions.

See [AgentKit Autogen](./framework-extensions/autogen/README.md)

### `create-onchain-agent`

A quickstart CLI tool to scaffold out a chatbot using Coinbase AgentKit. Runnable via `pipx run create-onchain-agent`.
Expand Down
8 changes: 8 additions & 0 deletions python/examples/autogen-cdp-chatbot/.env.local
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
# Required
CDP_API_KEY_ID=
CDP_API_KEY_SECRET=
CDP_WALLET_SECRET=
OPENAI_API_KEY=

# Optional with defaults
NETWORK_ID=base-sepolia
29 changes: 29 additions & 0 deletions python/examples/autogen-cdp-chatbot/Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
ifneq (,$(wildcard ./.env))
include .env
endif

export

.PHONY: install
install:
uv sync

.PHONY: run
run:
uv run chatbot.py

.PHONY: format
format:
uv run ruff format .

.PHONY: format-check
format-check:
uv run ruff format . --check

.PHONY: lint
lint:
uv run ruff check .

.PHONY: lint-fix
lint-fix:
uv run ruff check . --fix
50 changes: 50 additions & 0 deletions python/examples/autogen-cdp-chatbot/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
# CDP Agentkit Autogen Extension Examples - Chatbot Python

This example demonstrates an agent setup as a terminal style chatbot using Microsoft Autogen integration with CDP Agentkit actions.

## Ask the chatbot to engage in the Web3 ecosystem!

- "What is the price of BTC?"
- "Request some test tokens from the faucet"
- "What are my CDP account details?"
- "Transfer a portion of your ETH to a random address"
- "Deploy an NFT that will go super viral!"
- "Deploy an ERC-20 token with total supply 1 billion"

## Requirements

- Python 3.10+
- uv for package management and tooling
- [uv Installation Instructions](https://github.com/astral-sh/uv?tab=readme-ov-file#installation)
- [CDP API Key](https://portal.cdp.coinbase.com/access/api)
- [OpenAI API Key](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)

### Checking Python Version

Before using the example, ensure that you have the correct version of Python installed. The example requires Python 3.10 or higher. You can check your Python version by running:

```bash
python --version
uv --version
```

## Installation

```bash
make install
```

## Run the Chatbot

### Env

Rename .env.local to .env and ensure the following var are set:

- "CDP_API_KEY_ID"
- "CDP_API_KEY_SECRET"
- "CDP_WALLET_SECRET" # This is the wallet secret for the wallet you want to use for the chatbot
- "OPENAI_API_KEY"

```bash
make run
```
270 changes: 270 additions & 0 deletions python/examples/autogen-cdp-chatbot/chatbot.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
import asyncio
import json
import os
import time

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import BaseChatMessage, TextMessage
from autogen_core.memory import ListMemory
from autogen_ext.models.openai import OpenAIChatCompletionClient
from coinbase_agentkit import (
AgentKit,
AgentKitConfig,
CdpEvmWalletProvider,
CdpEvmWalletProviderConfig,
cdp_api_action_provider,
erc20_action_provider,
pyth_action_provider,
wallet_action_provider,
weth_action_provider,
x402_action_provider,
)
from coinbase_agentkit_autogen.autogen_tools import get_autogen_tools
from dotenv import load_dotenv


def initialize_agent(
config: CdpEvmWalletProviderConfig,
) -> tuple[AssistantAgent, CdpEvmWalletProvider]:
"""Initialize the agent with CDP Agentkit.

Args:
config: Configuration for the CDP EVM Server Wallet Provider

Returns:
tuple[Agent, CdpEvmServerWalletProvider]: The initialized agent and wallet provider

"""
# Initialize the language model
model_client = OpenAIChatCompletionClient(
model="gpt-4o-mini",
)

# Initialize the wallet provider with the config
wallet_provider = CdpEvmWalletProvider(
CdpEvmWalletProviderConfig(
api_key_id=config.api_key_id, # CDP API Key ID
api_key_secret=config.api_key_secret, # CDP API Key Secret
wallet_secret=config.wallet_secret, # CDP Wallet Secret
network_id=config.network_id, # Network ID - Optional, will default to 'base-sepolia'
address=config.address, # Wallet Address - Optional, will trigger idempotency flow if not provided
idempotency_key=config.idempotency_key, # Idempotency Key - Optional, seeds generation of a new wallet
rpc_url=config.rpc_url, # Optional RPC URL override
)
)

# Create AgentKit instance with wallet and action providers
agentkit = AgentKit(
AgentKitConfig(
wallet_provider=wallet_provider,
action_providers=[
cdp_api_action_provider(),
erc20_action_provider(),
pyth_action_provider(),
wallet_action_provider(),
weth_action_provider(),
x402_action_provider(),
],
)
)

# Get tools for the agent
tools = get_autogen_tools(agentkit)

# Set up conversation memory
memory = ListMemory()

# Set up Autogen Assistant Agent
agent = AssistantAgent(
name="assistant",
model_client=model_client,
reflect_on_tool_use=True,
tools=tools,
memory=[memory],
max_tool_iterations=3,
system_message=(
"You are a helpful agent that can interact onchain using the Coinbase Developer Platform AgentKit. "
"You are empowered to interact onchain using your tools. If you ever need funds, you can request "
"them from the faucet if you are on network ID 'base-sepolia'. If not, you can provide your wallet "
"details and request funds from the user. Before executing your first action, get the wallet details "
"to see what network you're on. If there is a 5XX (internal) HTTP error code, ask the user to try "
"again later. If someone asks you to do something you can't do with your currently available tools, "
"you must say so, and encourage them to implement it themselves using the CDP SDK + Agentkit, "
"recommend they go to docs.cdp.coinbase.com for more information. Be concise and helpful with your "
"responses. Refrain from restating your tools' descriptions unless it is explicitly requested."
),
)

# Create and return the agent and wallet provider
return agent, wallet_provider


def setup() -> AssistantAgent:
"""Set up the agent with persistent wallet storage.

Returns:
AssistantAgent: The initialized agent used for handling wallet interactions and
executing associated operations.

"""
# Configure network and file path
network_id = os.getenv("NETWORK_ID", "base-sepolia")
wallet_file = f"wallet_data_{network_id.replace('-', '_')}.txt"

# Load existing wallet data if available
wallet_data = {}
if os.path.exists(wallet_file):
try:
with open(wallet_file) as f:
wallet_data = json.load(f)
print(f"Loading existing wallet from {wallet_file}")
except json.JSONDecodeError:
print(f"Warning: Invalid wallet data for {network_id}")
wallet_data = {}

# Determine wallet address using priority order
wallet_address = (
wallet_data.get("address") # First priority: Saved wallet file
or os.getenv("ADDRESS") # Second priority: ADDRESS env var
or None # Will trigger idempotency flow if needed
)

# Create the wallet provider config
config = CdpEvmWalletProviderConfig(
api_key_id=os.getenv("CDP_API_KEY_ID"),
api_key_secret=os.getenv("CDP_API_KEY_SECRET"),
wallet_secret=os.getenv("CDP_WALLET_SECRET"),
network_id=network_id,
address=wallet_address,
# Only include idempotency_key if we need to create a new wallet
idempotency_key=(os.getenv("IDEMPOTENCY_KEY") if not wallet_address else None),
)

# Initialize the agent and get the wallet provider
agent_executor, wallet_provider = initialize_agent(config)

# Save the wallet data after successful initialization
new_wallet_data = {
"address": wallet_provider.get_address(),
"network_id": network_id,
"created_at": time.strftime("%Y-%m-%d %H:%M:%S")
if not wallet_data
else wallet_data.get("created_at"),
}

with open(wallet_file, "w") as f:
json.dump(new_wallet_data, f, indent=2)
print(f"Wallet data saved to {wallet_file}")

return agent_executor


# Autonomous Mode
async def run_autonomous_mode(agent_executor: AssistantAgent, interval=10) -> None:
"""Run the autonomous mode of the AssistantAgent with a specified interval between actions.

Args:
agent_executor (AssistantAgent): The agent responsible for executing tasks autonomously.
interval (int, optional): Time in seconds to wait between consecutive autonomous actions. Defaults to 10.

"""
print("Starting autonomous mode...")
while True:
try:
# Provide instructions autonomously
thought = (
"Be creative and do something interesting on the blockchain. "
"Choose an action or set of actions and execute it that highlights your abilities."
)

# Run agent in autonomous mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=thought, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

# Wait before the next action
await asyncio.sleep(interval)

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Chat Mode
async def run_chat_mode(agent_executor: AssistantAgent) -> None:
"""Run the assistant agent in chat mode.

Args:
agent_executor (AssistantAgent): The agent executor responsible for handling the
chatbot functionality and running tasks based on user input.

"""
print("Starting chat mode... Type 'exit' to end.")
while True:
try:
user_input = input("\nPrompt: ")
if user_input.lower() == "exit":
break

# Run agent with the user's input in chat mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=user_input, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Mode Selection
def choose_mode():
"""Prompt the user to select a mode of operation from the available options.

Returns
-------
str
The selected mode, either "chat" or "auto".

"""
while True:
print("\nAvailable modes:")
print("1. chat - Interactive chat mode")
print("2. auto - Autonomous action mode")

choice = input("\nChoose a mode (enter number or name): ").lower().strip()
if choice in ["1", "chat"]:
return "chat"
elif choice in ["2", "auto"]:
return "auto"
print("Invalid choice. Please try again.")


async def main():
"""Start the chatbot agent."""
# Load environment variables
load_dotenv()

# Set up the agent
agent_executor = setup()

# Run the agent in the selected mode
mode = choose_mode()
if mode == "chat":
await run_chat_mode(agent_executor=agent_executor)
elif mode == "auto":
await run_autonomous_mode(agent_executor=agent_executor)


if __name__ == "__main__":
print("Starting Agent...")
asyncio.run(main())
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions python/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,6 +34,12 @@ PydanticAI extension of AgentKit. Enables agentic workflows to interact with onc

See [AgentKit PydanticAI](./framework-extensions/pydantic-ai/README.md) to get started!

#### `coinbase-agentkit-autogen`

Microsoft Autogen extension of AgentKit. Enables agentic workflows to interact with onchain actions.

See [AgentKit Autogen](./framework-extensions/autogen/README.md)

### `create-onchain-agent`

A quickstart CLI tool to scaffold out a chatbot using Coinbase AgentKit. Runnable via `pipx run create-onchain-agent`.
Expand Down
8 changes: 8 additions & 0 deletions python/examples/autogen-cdp-chatbot/.env.local
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
# Required
CDP_API_KEY_ID=
CDP_API_KEY_SECRET=
CDP_WALLET_SECRET=
OPENAI_API_KEY=

# Optional with defaults
NETWORK_ID=base-sepolia
29 changes: 29 additions & 0 deletions python/examples/autogen-cdp-chatbot/Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
ifneq (,$(wildcard ./.env))
include .env
endif

export

.PHONY: install
install:
uv sync

.PHONY: run
run:
uv run chatbot.py

.PHONY: format
format:
uv run ruff format .

.PHONY: format-check
format-check:
uv run ruff format . --check

.PHONY: lint
lint:
uv run ruff check .

.PHONY: lint-fix
lint-fix:
uv run ruff check . --fix
50 changes: 50 additions & 0 deletions python/examples/autogen-cdp-chatbot/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
# CDP Agentkit Autogen Extension Examples - Chatbot Python

This example demonstrates an agent setup as a terminal style chatbot using Microsoft Autogen integration with CDP Agentkit actions.

## Ask the chatbot to engage in the Web3 ecosystem!

- "What is the price of BTC?"
- "Request some test tokens from the faucet"
- "What are my CDP account details?"
- "Transfer a portion of your ETH to a random address"
- "Deploy an NFT that will go super viral!"
- "Deploy an ERC-20 token with total supply 1 billion"

## Requirements

- Python 3.10+
- uv for package management and tooling
- [uv Installation Instructions](https://github.com/astral-sh/uv?tab=readme-ov-file#installation)
- [CDP API Key](https://portal.cdp.coinbase.com/access/api)
- [OpenAI API Key](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)

### Checking Python Version

Before using the example, ensure that you have the correct version of Python installed. The example requires Python 3.10 or higher. You can check your Python version by running:

```bash
python --version
uv --version
```

## Installation

```bash
make install
```

## Run the Chatbot

### Env

Rename .env.local to .env and ensure the following var are set:

- "CDP_API_KEY_ID"
- "CDP_API_KEY_SECRET"
- "CDP_WALLET_SECRET" # This is the wallet secret for the wallet you want to use for the chatbot
- "OPENAI_API_KEY"

```bash
make run
```
270 changes: 270 additions & 0 deletions python/examples/autogen-cdp-chatbot/chatbot.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
import asyncio
import json
import os
import time

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import BaseChatMessage, TextMessage
from autogen_core.memory import ListMemory
from autogen_ext.models.openai import OpenAIChatCompletionClient
from coinbase_agentkit import (
AgentKit,
AgentKitConfig,
CdpEvmWalletProvider,
CdpEvmWalletProviderConfig,
cdp_api_action_provider,
erc20_action_provider,
pyth_action_provider,
wallet_action_provider,
weth_action_provider,
x402_action_provider,
)
from coinbase_agentkit_autogen.autogen_tools import get_autogen_tools
from dotenv import load_dotenv


def initialize_agent(
config: CdpEvmWalletProviderConfig,
) -> tuple[AssistantAgent, CdpEvmWalletProvider]:
"""Initialize the agent with CDP Agentkit.

Args:
config: Configuration for the CDP EVM Server Wallet Provider

Returns:
tuple[Agent, CdpEvmServerWalletProvider]: The initialized agent and wallet provider

"""
# Initialize the language model
model_client = OpenAIChatCompletionClient(
model="gpt-4o-mini",
)

# Initialize the wallet provider with the config
wallet_provider = CdpEvmWalletProvider(
CdpEvmWalletProviderConfig(
api_key_id=config.api_key_id, # CDP API Key ID
api_key_secret=config.api_key_secret, # CDP API Key Secret
wallet_secret=config.wallet_secret, # CDP Wallet Secret
network_id=config.network_id, # Network ID - Optional, will default to 'base-sepolia'
address=config.address, # Wallet Address - Optional, will trigger idempotency flow if not provided
idempotency_key=config.idempotency_key, # Idempotency Key - Optional, seeds generation of a new wallet
rpc_url=config.rpc_url, # Optional RPC URL override
)
)

# Create AgentKit instance with wallet and action providers
agentkit = AgentKit(
AgentKitConfig(
wallet_provider=wallet_provider,
action_providers=[
cdp_api_action_provider(),
erc20_action_provider(),
pyth_action_provider(),
wallet_action_provider(),
weth_action_provider(),
x402_action_provider(),
],
)
)

# Get tools for the agent
tools = get_autogen_tools(agentkit)

# Set up conversation memory
memory = ListMemory()

# Set up Autogen Assistant Agent
agent = AssistantAgent(
name="assistant",
model_client=model_client,
reflect_on_tool_use=True,
tools=tools,
memory=[memory],
max_tool_iterations=3,
system_message=(
"You are a helpful agent that can interact onchain using the Coinbase Developer Platform AgentKit. "
"You are empowered to interact onchain using your tools. If you ever need funds, you can request "
"them from the faucet if you are on network ID 'base-sepolia'. If not, you can provide your wallet "
"details and request funds from the user. Before executing your first action, get the wallet details "
"to see what network you're on. If there is a 5XX (internal) HTTP error code, ask the user to try "
"again later. If someone asks you to do something you can't do with your currently available tools, "
"you must say so, and encourage them to implement it themselves using the CDP SDK + Agentkit, "
"recommend they go to docs.cdp.coinbase.com for more information. Be concise and helpful with your "
"responses. Refrain from restating your tools' descriptions unless it is explicitly requested."
),
)

# Create and return the agent and wallet provider
return agent, wallet_provider


def setup() -> AssistantAgent:
"""Set up the agent with persistent wallet storage.

Returns:
AssistantAgent: The initialized agent used for handling wallet interactions and
executing associated operations.

"""
# Configure network and file path
network_id = os.getenv("NETWORK_ID", "base-sepolia")
wallet_file = f"wallet_data_{network_id.replace('-', '_')}.txt"

# Load existing wallet data if available
wallet_data = {}
if os.path.exists(wallet_file):
try:
with open(wallet_file) as f:
wallet_data = json.load(f)
print(f"Loading existing wallet from {wallet_file}")
except json.JSONDecodeError:
print(f"Warning: Invalid wallet data for {network_id}")
wallet_data = {}

# Determine wallet address using priority order
wallet_address = (
wallet_data.get("address") # First priority: Saved wallet file
or os.getenv("ADDRESS") # Second priority: ADDRESS env var
or None # Will trigger idempotency flow if needed
)

# Create the wallet provider config
config = CdpEvmWalletProviderConfig(
api_key_id=os.getenv("CDP_API_KEY_ID"),
api_key_secret=os.getenv("CDP_API_KEY_SECRET"),
wallet_secret=os.getenv("CDP_WALLET_SECRET"),
network_id=network_id,
address=wallet_address,
# Only include idempotency_key if we need to create a new wallet
idempotency_key=(os.getenv("IDEMPOTENCY_KEY") if not wallet_address else None),
)

# Initialize the agent and get the wallet provider
agent_executor, wallet_provider = initialize_agent(config)

# Save the wallet data after successful initialization
new_wallet_data = {
"address": wallet_provider.get_address(),
"network_id": network_id,
"created_at": time.strftime("%Y-%m-%d %H:%M:%S")
if not wallet_data
else wallet_data.get("created_at"),
}

with open(wallet_file, "w") as f:
json.dump(new_wallet_data, f, indent=2)
print(f"Wallet data saved to {wallet_file}")

return agent_executor


# Autonomous Mode
async def run_autonomous_mode(agent_executor: AssistantAgent, interval=10) -> None:
"""Run the autonomous mode of the AssistantAgent with a specified interval between actions.

Args:
agent_executor (AssistantAgent): The agent responsible for executing tasks autonomously.
interval (int, optional): Time in seconds to wait between consecutive autonomous actions. Defaults to 10.

"""
print("Starting autonomous mode...")
while True:
try:
# Provide instructions autonomously
thought = (
"Be creative and do something interesting on the blockchain. "
"Choose an action or set of actions and execute it that highlights your abilities."
)

# Run agent in autonomous mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=thought, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

# Wait before the next action
await asyncio.sleep(interval)

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Chat Mode
async def run_chat_mode(agent_executor: AssistantAgent) -> None:
"""Run the assistant agent in chat mode.

Args:
agent_executor (AssistantAgent): The agent executor responsible for handling the
chatbot functionality and running tasks based on user input.

"""
print("Starting chat mode... Type 'exit' to end.")
while True:
try:
user_input = input("\nPrompt: ")
if user_input.lower() == "exit":
break

# Run agent with the user's input in chat mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=user_input, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Mode Selection
def choose_mode():
"""Prompt the user to select a mode of operation from the available options.

Returns
-------
str
The selected mode, either "chat" or "auto".

"""
while True:
print("\nAvailable modes:")
print("1. chat - Interactive chat mode")
print("2. auto - Autonomous action mode")

choice = input("\nChoose a mode (enter number or name): ").lower().strip()
if choice in ["1", "chat"]:
return "chat"
elif choice in ["2", "auto"]:
return "auto"
print("Invalid choice. Please try again.")


async def main():
"""Start the chatbot agent."""
# Load environment variables
load_dotenv()

# Set up the agent
agent_executor = setup()

# Run the agent in the selected mode
mode = choose_mode()
if mode == "chat":
await run_chat_mode(agent_executor=agent_executor)
elif mode == "auto":
await run_autonomous_mode(agent_executor=agent_executor)


if __name__ == "__main__":
print("Starting Agent...")
asyncio.run(main())
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions python/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,6 +34,12 @@ PydanticAI extension of AgentKit. Enables agentic workflows to interact with onc

See [AgentKit PydanticAI](./framework-extensions/pydantic-ai/README.md) to get started!

#### `coinbase-agentkit-autogen`

Microsoft Autogen extension of AgentKit. Enables agentic workflows to interact with onchain actions.

See [AgentKit Autogen](./framework-extensions/autogen/README.md)

### `create-onchain-agent`

A quickstart CLI tool to scaffold out a chatbot using Coinbase AgentKit. Runnable via `pipx run create-onchain-agent`.
Expand Down
8 changes: 8 additions & 0 deletions python/examples/autogen-cdp-chatbot/.env.local
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
# Required
CDP_API_KEY_ID=
CDP_API_KEY_SECRET=
CDP_WALLET_SECRET=
OPENAI_API_KEY=

# Optional with defaults
NETWORK_ID=base-sepolia
29 changes: 29 additions & 0 deletions python/examples/autogen-cdp-chatbot/Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
ifneq (,$(wildcard ./.env))
include .env
endif

export

.PHONY: install
install:
uv sync

.PHONY: run
run:
uv run chatbot.py

.PHONY: format
format:
uv run ruff format .

.PHONY: format-check
format-check:
uv run ruff format . --check

.PHONY: lint
lint:
uv run ruff check .

.PHONY: lint-fix
lint-fix:
uv run ruff check . --fix
50 changes: 50 additions & 0 deletions python/examples/autogen-cdp-chatbot/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
# CDP Agentkit Autogen Extension Examples - Chatbot Python

This example demonstrates an agent setup as a terminal style chatbot using Microsoft Autogen integration with CDP Agentkit actions.

## Ask the chatbot to engage in the Web3 ecosystem!

- "What is the price of BTC?"
- "Request some test tokens from the faucet"
- "What are my CDP account details?"
- "Transfer a portion of your ETH to a random address"
- "Deploy an NFT that will go super viral!"
- "Deploy an ERC-20 token with total supply 1 billion"

## Requirements

- Python 3.10+
- uv for package management and tooling
- [uv Installation Instructions](https://github.com/astral-sh/uv?tab=readme-ov-file#installation)
- [CDP API Key](https://portal.cdp.coinbase.com/access/api)
- [OpenAI API Key](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)

### Checking Python Version

Before using the example, ensure that you have the correct version of Python installed. The example requires Python 3.10 or higher. You can check your Python version by running:

```bash
python --version
uv --version
```

## Installation

```bash
make install
```

## Run the Chatbot

### Env

Rename .env.local to .env and ensure the following var are set:

- "CDP_API_KEY_ID"
- "CDP_API_KEY_SECRET"
- "CDP_WALLET_SECRET" # This is the wallet secret for the wallet you want to use for the chatbot
- "OPENAI_API_KEY"

```bash
make run
```
270 changes: 270 additions & 0 deletions python/examples/autogen-cdp-chatbot/chatbot.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
import asyncio
import json
import os
import time

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import BaseChatMessage, TextMessage
from autogen_core.memory import ListMemory
from autogen_ext.models.openai import OpenAIChatCompletionClient
from coinbase_agentkit import (
AgentKit,
AgentKitConfig,
CdpEvmWalletProvider,
CdpEvmWalletProviderConfig,
cdp_api_action_provider,
erc20_action_provider,
pyth_action_provider,
wallet_action_provider,
weth_action_provider,
x402_action_provider,
)
from coinbase_agentkit_autogen.autogen_tools import get_autogen_tools
from dotenv import load_dotenv


def initialize_agent(
config: CdpEvmWalletProviderConfig,
) -> tuple[AssistantAgent, CdpEvmWalletProvider]:
"""Initialize the agent with CDP Agentkit.

Args:
config: Configuration for the CDP EVM Server Wallet Provider

Returns:
tuple[Agent, CdpEvmServerWalletProvider]: The initialized agent and wallet provider

"""
# Initialize the language model
model_client = OpenAIChatCompletionClient(
model="gpt-4o-mini",
)

# Initialize the wallet provider with the config
wallet_provider = CdpEvmWalletProvider(
CdpEvmWalletProviderConfig(
api_key_id=config.api_key_id, # CDP API Key ID
api_key_secret=config.api_key_secret, # CDP API Key Secret
wallet_secret=config.wallet_secret, # CDP Wallet Secret
network_id=config.network_id, # Network ID - Optional, will default to 'base-sepolia'
address=config.address, # Wallet Address - Optional, will trigger idempotency flow if not provided
idempotency_key=config.idempotency_key, # Idempotency Key - Optional, seeds generation of a new wallet
rpc_url=config.rpc_url, # Optional RPC URL override
)
)

# Create AgentKit instance with wallet and action providers
agentkit = AgentKit(
AgentKitConfig(
wallet_provider=wallet_provider,
action_providers=[
cdp_api_action_provider(),
erc20_action_provider(),
pyth_action_provider(),
wallet_action_provider(),
weth_action_provider(),
x402_action_provider(),
],
)
)

# Get tools for the agent
tools = get_autogen_tools(agentkit)

# Set up conversation memory
memory = ListMemory()

# Set up Autogen Assistant Agent
agent = AssistantAgent(
name="assistant",
model_client=model_client,
reflect_on_tool_use=True,
tools=tools,
memory=[memory],
max_tool_iterations=3,
system_message=(
"You are a helpful agent that can interact onchain using the Coinbase Developer Platform AgentKit. "
"You are empowered to interact onchain using your tools. If you ever need funds, you can request "
"them from the faucet if you are on network ID 'base-sepolia'. If not, you can provide your wallet "
"details and request funds from the user. Before executing your first action, get the wallet details "
"to see what network you're on. If there is a 5XX (internal) HTTP error code, ask the user to try "
"again later. If someone asks you to do something you can't do with your currently available tools, "
"you must say so, and encourage them to implement it themselves using the CDP SDK + Agentkit, "
"recommend they go to docs.cdp.coinbase.com for more information. Be concise and helpful with your "
"responses. Refrain from restating your tools' descriptions unless it is explicitly requested."
),
)

# Create and return the agent and wallet provider
return agent, wallet_provider


def setup() -> AssistantAgent:
"""Set up the agent with persistent wallet storage.

Returns:
AssistantAgent: The initialized agent used for handling wallet interactions and
executing associated operations.

"""
# Configure network and file path
network_id = os.getenv("NETWORK_ID", "base-sepolia")
wallet_file = f"wallet_data_{network_id.replace('-', '_')}.txt"

# Load existing wallet data if available
wallet_data = {}
if os.path.exists(wallet_file):
try:
with open(wallet_file) as f:
wallet_data = json.load(f)
print(f"Loading existing wallet from {wallet_file}")
except json.JSONDecodeError:
print(f"Warning: Invalid wallet data for {network_id}")
wallet_data = {}

# Determine wallet address using priority order
wallet_address = (
wallet_data.get("address") # First priority: Saved wallet file
or os.getenv("ADDRESS") # Second priority: ADDRESS env var
or None # Will trigger idempotency flow if needed
)

# Create the wallet provider config
config = CdpEvmWalletProviderConfig(
api_key_id=os.getenv("CDP_API_KEY_ID"),
api_key_secret=os.getenv("CDP_API_KEY_SECRET"),
wallet_secret=os.getenv("CDP_WALLET_SECRET"),
network_id=network_id,
address=wallet_address,
# Only include idempotency_key if we need to create a new wallet
idempotency_key=(os.getenv("IDEMPOTENCY_KEY") if not wallet_address else None),
)

# Initialize the agent and get the wallet provider
agent_executor, wallet_provider = initialize_agent(config)

# Save the wallet data after successful initialization
new_wallet_data = {
"address": wallet_provider.get_address(),
"network_id": network_id,
"created_at": time.strftime("%Y-%m-%d %H:%M:%S")
if not wallet_data
else wallet_data.get("created_at"),
}

with open(wallet_file, "w") as f:
json.dump(new_wallet_data, f, indent=2)
print(f"Wallet data saved to {wallet_file}")

return agent_executor


# Autonomous Mode
async def run_autonomous_mode(agent_executor: AssistantAgent, interval=10) -> None:
"""Run the autonomous mode of the AssistantAgent with a specified interval between actions.

Args:
agent_executor (AssistantAgent): The agent responsible for executing tasks autonomously.
interval (int, optional): Time in seconds to wait between consecutive autonomous actions. Defaults to 10.

"""
print("Starting autonomous mode...")
while True:
try:
# Provide instructions autonomously
thought = (
"Be creative and do something interesting on the blockchain. "
"Choose an action or set of actions and execute it that highlights your abilities."
)

# Run agent in autonomous mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=thought, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

# Wait before the next action
await asyncio.sleep(interval)

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Chat Mode
async def run_chat_mode(agent_executor: AssistantAgent) -> None:
"""Run the assistant agent in chat mode.

Args:
agent_executor (AssistantAgent): The agent executor responsible for handling the
chatbot functionality and running tasks based on user input.

"""
print("Starting chat mode... Type 'exit' to end.")
while True:
try:
user_input = input("\nPrompt: ")
if user_input.lower() == "exit":
break

# Run agent with the user's input in chat mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=user_input, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Mode Selection
def choose_mode():
"""Prompt the user to select a mode of operation from the available options.

Returns
-------
str
The selected mode, either "chat" or "auto".

"""
while True:
print("\nAvailable modes:")
print("1. chat - Interactive chat mode")
print("2. auto - Autonomous action mode")

choice = input("\nChoose a mode (enter number or name): ").lower().strip()
if choice in ["1", "chat"]:
return "chat"
elif choice in ["2", "auto"]:
return "auto"
print("Invalid choice. Please try again.")


async def main():
"""Start the chatbot agent."""
# Load environment variables
load_dotenv()

# Set up the agent
agent_executor = setup()

# Run the agent in the selected mode
mode = choose_mode()
if mode == "chat":
await run_chat_mode(agent_executor=agent_executor)
elif mode == "auto":
await run_autonomous_mode(agent_executor=agent_executor)


if __name__ == "__main__":
print("Starting Agent...")
asyncio.run(main())
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions python/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,6 +34,12 @@ PydanticAI extension of AgentKit. Enables agentic workflows to interact with onc

See [AgentKit PydanticAI](./framework-extensions/pydantic-ai/README.md) to get started!

#### `coinbase-agentkit-autogen`

Microsoft Autogen extension of AgentKit. Enables agentic workflows to interact with onchain actions.

See [AgentKit Autogen](./framework-extensions/autogen/README.md)

### `create-onchain-agent`

A quickstart CLI tool to scaffold out a chatbot using Coinbase AgentKit. Runnable via `pipx run create-onchain-agent`.
Expand Down
8 changes: 8 additions & 0 deletions python/examples/autogen-cdp-chatbot/.env.local
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
# Required
CDP_API_KEY_ID=
CDP_API_KEY_SECRET=
CDP_WALLET_SECRET=
OPENAI_API_KEY=

# Optional with defaults
NETWORK_ID=base-sepolia
29 changes: 29 additions & 0 deletions python/examples/autogen-cdp-chatbot/Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
ifneq (,$(wildcard ./.env))
include .env
endif

export

.PHONY: install
install:
uv sync

.PHONY: run
run:
uv run chatbot.py

.PHONY: format
format:
uv run ruff format .

.PHONY: format-check
format-check:
uv run ruff format . --check

.PHONY: lint
lint:
uv run ruff check .

.PHONY: lint-fix
lint-fix:
uv run ruff check . --fix
50 changes: 50 additions & 0 deletions python/examples/autogen-cdp-chatbot/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
# CDP Agentkit Autogen Extension Examples - Chatbot Python

This example demonstrates an agent setup as a terminal style chatbot using Microsoft Autogen integration with CDP Agentkit actions.

## Ask the chatbot to engage in the Web3 ecosystem!

- "What is the price of BTC?"
- "Request some test tokens from the faucet"
- "What are my CDP account details?"
- "Transfer a portion of your ETH to a random address"
- "Deploy an NFT that will go super viral!"
- "Deploy an ERC-20 token with total supply 1 billion"

## Requirements

- Python 3.10+
- uv for package management and tooling
- [uv Installation Instructions](https://github.com/astral-sh/uv?tab=readme-ov-file#installation)
- [CDP API Key](https://portal.cdp.coinbase.com/access/api)
- [OpenAI API Key](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)

### Checking Python Version

Before using the example, ensure that you have the correct version of Python installed. The example requires Python 3.10 or higher. You can check your Python version by running:

```bash
python --version
uv --version
```

## Installation

```bash
make install
```

## Run the Chatbot

### Env

Rename .env.local to .env and ensure the following var are set:

- "CDP_API_KEY_ID"
- "CDP_API_KEY_SECRET"
- "CDP_WALLET_SECRET" # This is the wallet secret for the wallet you want to use for the chatbot
- "OPENAI_API_KEY"

```bash
make run
```
270 changes: 270 additions & 0 deletions python/examples/autogen-cdp-chatbot/chatbot.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
import asyncio
import json
import os
import time

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import BaseChatMessage, TextMessage
from autogen_core.memory import ListMemory
from autogen_ext.models.openai import OpenAIChatCompletionClient
from coinbase_agentkit import (
AgentKit,
AgentKitConfig,
CdpEvmWalletProvider,
CdpEvmWalletProviderConfig,
cdp_api_action_provider,
erc20_action_provider,
pyth_action_provider,
wallet_action_provider,
weth_action_provider,
x402_action_provider,
)
from coinbase_agentkit_autogen.autogen_tools import get_autogen_tools
from dotenv import load_dotenv


def initialize_agent(
config: CdpEvmWalletProviderConfig,
) -> tuple[AssistantAgent, CdpEvmWalletProvider]:
"""Initialize the agent with CDP Agentkit.

Args:
config: Configuration for the CDP EVM Server Wallet Provider

Returns:
tuple[Agent, CdpEvmServerWalletProvider]: The initialized agent and wallet provider

"""
# Initialize the language model
model_client = OpenAIChatCompletionClient(
model="gpt-4o-mini",
)

# Initialize the wallet provider with the config
wallet_provider = CdpEvmWalletProvider(
CdpEvmWalletProviderConfig(
api_key_id=config.api_key_id, # CDP API Key ID
api_key_secret=config.api_key_secret, # CDP API Key Secret
wallet_secret=config.wallet_secret, # CDP Wallet Secret
network_id=config.network_id, # Network ID - Optional, will default to 'base-sepolia'
address=config.address, # Wallet Address - Optional, will trigger idempotency flow if not provided
idempotency_key=config.idempotency_key, # Idempotency Key - Optional, seeds generation of a new wallet
rpc_url=config.rpc_url, # Optional RPC URL override
)
)

# Create AgentKit instance with wallet and action providers
agentkit = AgentKit(
AgentKitConfig(
wallet_provider=wallet_provider,
action_providers=[
cdp_api_action_provider(),
erc20_action_provider(),
pyth_action_provider(),
wallet_action_provider(),
weth_action_provider(),
x402_action_provider(),
],
)
)

# Get tools for the agent
tools = get_autogen_tools(agentkit)

# Set up conversation memory
memory = ListMemory()

# Set up Autogen Assistant Agent
agent = AssistantAgent(
name="assistant",
model_client=model_client,
reflect_on_tool_use=True,
tools=tools,
memory=[memory],
max_tool_iterations=3,
system_message=(
"You are a helpful agent that can interact onchain using the Coinbase Developer Platform AgentKit. "
"You are empowered to interact onchain using your tools. If you ever need funds, you can request "
"them from the faucet if you are on network ID 'base-sepolia'. If not, you can provide your wallet "
"details and request funds from the user. Before executing your first action, get the wallet details "
"to see what network you're on. If there is a 5XX (internal) HTTP error code, ask the user to try "
"again later. If someone asks you to do something you can't do with your currently available tools, "
"you must say so, and encourage them to implement it themselves using the CDP SDK + Agentkit, "
"recommend they go to docs.cdp.coinbase.com for more information. Be concise and helpful with your "
"responses. Refrain from restating your tools' descriptions unless it is explicitly requested."
),
)

# Create and return the agent and wallet provider
return agent, wallet_provider


def setup() -> AssistantAgent:
"""Set up the agent with persistent wallet storage.

Returns:
AssistantAgent: The initialized agent used for handling wallet interactions and
executing associated operations.

"""
# Configure network and file path
network_id = os.getenv("NETWORK_ID", "base-sepolia")
wallet_file = f"wallet_data_{network_id.replace('-', '_')}.txt"

# Load existing wallet data if available
wallet_data = {}
if os.path.exists(wallet_file):
try:
with open(wallet_file) as f:
wallet_data = json.load(f)
print(f"Loading existing wallet from {wallet_file}")
except json.JSONDecodeError:
print(f"Warning: Invalid wallet data for {network_id}")
wallet_data = {}

# Determine wallet address using priority order
wallet_address = (
wallet_data.get("address") # First priority: Saved wallet file
or os.getenv("ADDRESS") # Second priority: ADDRESS env var
or None # Will trigger idempotency flow if needed
)

# Create the wallet provider config
config = CdpEvmWalletProviderConfig(
api_key_id=os.getenv("CDP_API_KEY_ID"),
api_key_secret=os.getenv("CDP_API_KEY_SECRET"),
wallet_secret=os.getenv("CDP_WALLET_SECRET"),
network_id=network_id,
address=wallet_address,
# Only include idempotency_key if we need to create a new wallet
idempotency_key=(os.getenv("IDEMPOTENCY_KEY") if not wallet_address else None),
)

# Initialize the agent and get the wallet provider
agent_executor, wallet_provider = initialize_agent(config)

# Save the wallet data after successful initialization
new_wallet_data = {
"address": wallet_provider.get_address(),
"network_id": network_id,
"created_at": time.strftime("%Y-%m-%d %H:%M:%S")
if not wallet_data
else wallet_data.get("created_at"),
}

with open(wallet_file, "w") as f:
json.dump(new_wallet_data, f, indent=2)
print(f"Wallet data saved to {wallet_file}")

return agent_executor


# Autonomous Mode
async def run_autonomous_mode(agent_executor: AssistantAgent, interval=10) -> None:
"""Run the autonomous mode of the AssistantAgent with a specified interval between actions.

Args:
agent_executor (AssistantAgent): The agent responsible for executing tasks autonomously.
interval (int, optional): Time in seconds to wait between consecutive autonomous actions. Defaults to 10.

"""
print("Starting autonomous mode...")
while True:
try:
# Provide instructions autonomously
thought = (
"Be creative and do something interesting on the blockchain. "
"Choose an action or set of actions and execute it that highlights your abilities."
)

# Run agent in autonomous mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=thought, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

# Wait before the next action
await asyncio.sleep(interval)

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Chat Mode
async def run_chat_mode(agent_executor: AssistantAgent) -> None:
"""Run the assistant agent in chat mode.

Args:
agent_executor (AssistantAgent): The agent executor responsible for handling the
chatbot functionality and running tasks based on user input.

"""
print("Starting chat mode... Type 'exit' to end.")
while True:
try:
user_input = input("\nPrompt: ")
if user_input.lower() == "exit":
break

# Run agent with the user's input in chat mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=user_input, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Mode Selection
def choose_mode():
"""Prompt the user to select a mode of operation from the available options.

Returns
-------
str
The selected mode, either "chat" or "auto".

"""
while True:
print("\nAvailable modes:")
print("1. chat - Interactive chat mode")
print("2. auto - Autonomous action mode")

choice = input("\nChoose a mode (enter number or name): ").lower().strip()
if choice in ["1", "chat"]:
return "chat"
elif choice in ["2", "auto"]:
return "auto"
print("Invalid choice. Please try again.")


async def main():
"""Start the chatbot agent."""
# Load environment variables
load_dotenv()

# Set up the agent
agent_executor = setup()

# Run the agent in the selected mode
mode = choose_mode()
if mode == "chat":
await run_chat_mode(agent_executor=agent_executor)
elif mode == "auto":
await run_autonomous_mode(agent_executor=agent_executor)


if __name__ == "__main__":
print("Starting Agent...")
asyncio.run(main())
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions python/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,6 +34,12 @@ PydanticAI extension of AgentKit. Enables agentic workflows to interact with onc

See [AgentKit PydanticAI](./framework-extensions/pydantic-ai/README.md) to get started!

#### `coinbase-agentkit-autogen`

Microsoft Autogen extension of AgentKit. Enables agentic workflows to interact with onchain actions.

See [AgentKit Autogen](./framework-extensions/autogen/README.md)

### `create-onchain-agent`

A quickstart CLI tool to scaffold out a chatbot using Coinbase AgentKit. Runnable via `pipx run create-onchain-agent`.
Expand Down
8 changes: 8 additions & 0 deletions python/examples/autogen-cdp-chatbot/.env.local
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
# Required
CDP_API_KEY_ID=
CDP_API_KEY_SECRET=
CDP_WALLET_SECRET=
OPENAI_API_KEY=

# Optional with defaults
NETWORK_ID=base-sepolia
29 changes: 29 additions & 0 deletions python/examples/autogen-cdp-chatbot/Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
ifneq (,$(wildcard ./.env))
include .env
endif

export

.PHONY: install
install:
uv sync

.PHONY: run
run:
uv run chatbot.py

.PHONY: format
format:
uv run ruff format .

.PHONY: format-check
format-check:
uv run ruff format . --check

.PHONY: lint
lint:
uv run ruff check .

.PHONY: lint-fix
lint-fix:
uv run ruff check . --fix
50 changes: 50 additions & 0 deletions python/examples/autogen-cdp-chatbot/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
# CDP Agentkit Autogen Extension Examples - Chatbot Python

This example demonstrates an agent setup as a terminal style chatbot using Microsoft Autogen integration with CDP Agentkit actions.

## Ask the chatbot to engage in the Web3 ecosystem!

- "What is the price of BTC?"
- "Request some test tokens from the faucet"
- "What are my CDP account details?"
- "Transfer a portion of your ETH to a random address"
- "Deploy an NFT that will go super viral!"
- "Deploy an ERC-20 token with total supply 1 billion"

## Requirements

- Python 3.10+
- uv for package management and tooling
- [uv Installation Instructions](https://github.com/astral-sh/uv?tab=readme-ov-file#installation)
- [CDP API Key](https://portal.cdp.coinbase.com/access/api)
- [OpenAI API Key](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)

### Checking Python Version

Before using the example, ensure that you have the correct version of Python installed. The example requires Python 3.10 or higher. You can check your Python version by running:

```bash
python --version
uv --version
```

## Installation

```bash
make install
```

## Run the Chatbot

### Env

Rename .env.local to .env and ensure the following var are set:

- "CDP_API_KEY_ID"
- "CDP_API_KEY_SECRET"
- "CDP_WALLET_SECRET" # This is the wallet secret for the wallet you want to use for the chatbot
- "OPENAI_API_KEY"

```bash
make run
```
270 changes: 270 additions & 0 deletions python/examples/autogen-cdp-chatbot/chatbot.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
import asyncio
import json
import os
import time

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import BaseChatMessage, TextMessage
from autogen_core.memory import ListMemory
from autogen_ext.models.openai import OpenAIChatCompletionClient
from coinbase_agentkit import (
AgentKit,
AgentKitConfig,
CdpEvmWalletProvider,
CdpEvmWalletProviderConfig,
cdp_api_action_provider,
erc20_action_provider,
pyth_action_provider,
wallet_action_provider,
weth_action_provider,
x402_action_provider,
)
from coinbase_agentkit_autogen.autogen_tools import get_autogen_tools
from dotenv import load_dotenv


def initialize_agent(
config: CdpEvmWalletProviderConfig,
) -> tuple[AssistantAgent, CdpEvmWalletProvider]:
"""Initialize the agent with CDP Agentkit.

Args:
config: Configuration for the CDP EVM Server Wallet Provider

Returns:
tuple[Agent, CdpEvmServerWalletProvider]: The initialized agent and wallet provider

"""
# Initialize the language model
model_client = OpenAIChatCompletionClient(
model="gpt-4o-mini",
)

# Initialize the wallet provider with the config
wallet_provider = CdpEvmWalletProvider(
CdpEvmWalletProviderConfig(
api_key_id=config.api_key_id, # CDP API Key ID
api_key_secret=config.api_key_secret, # CDP API Key Secret
wallet_secret=config.wallet_secret, # CDP Wallet Secret
network_id=config.network_id, # Network ID - Optional, will default to 'base-sepolia'
address=config.address, # Wallet Address - Optional, will trigger idempotency flow if not provided
idempotency_key=config.idempotency_key, # Idempotency Key - Optional, seeds generation of a new wallet
rpc_url=config.rpc_url, # Optional RPC URL override
)
)

# Create AgentKit instance with wallet and action providers
agentkit = AgentKit(
AgentKitConfig(
wallet_provider=wallet_provider,
action_providers=[
cdp_api_action_provider(),
erc20_action_provider(),
pyth_action_provider(),
wallet_action_provider(),
weth_action_provider(),
x402_action_provider(),
],
)
)

# Get tools for the agent
tools = get_autogen_tools(agentkit)

# Set up conversation memory
memory = ListMemory()

# Set up Autogen Assistant Agent
agent = AssistantAgent(
name="assistant",
model_client=model_client,
reflect_on_tool_use=True,
tools=tools,
memory=[memory],
max_tool_iterations=3,
system_message=(
"You are a helpful agent that can interact onchain using the Coinbase Developer Platform AgentKit. "
"You are empowered to interact onchain using your tools. If you ever need funds, you can request "
"them from the faucet if you are on network ID 'base-sepolia'. If not, you can provide your wallet "
"details and request funds from the user. Before executing your first action, get the wallet details "
"to see what network you're on. If there is a 5XX (internal) HTTP error code, ask the user to try "
"again later. If someone asks you to do something you can't do with your currently available tools, "
"you must say so, and encourage them to implement it themselves using the CDP SDK + Agentkit, "
"recommend they go to docs.cdp.coinbase.com for more information. Be concise and helpful with your "
"responses. Refrain from restating your tools' descriptions unless it is explicitly requested."
),
)

# Create and return the agent and wallet provider
return agent, wallet_provider


def setup() -> AssistantAgent:
"""Set up the agent with persistent wallet storage.

Returns:
AssistantAgent: The initialized agent used for handling wallet interactions and
executing associated operations.

"""
# Configure network and file path
network_id = os.getenv("NETWORK_ID", "base-sepolia")
wallet_file = f"wallet_data_{network_id.replace('-', '_')}.txt"

# Load existing wallet data if available
wallet_data = {}
if os.path.exists(wallet_file):
try:
with open(wallet_file) as f:
wallet_data = json.load(f)
print(f"Loading existing wallet from {wallet_file}")
except json.JSONDecodeError:
print(f"Warning: Invalid wallet data for {network_id}")
wallet_data = {}

# Determine wallet address using priority order
wallet_address = (
wallet_data.get("address") # First priority: Saved wallet file
or os.getenv("ADDRESS") # Second priority: ADDRESS env var
or None # Will trigger idempotency flow if needed
)

# Create the wallet provider config
config = CdpEvmWalletProviderConfig(
api_key_id=os.getenv("CDP_API_KEY_ID"),
api_key_secret=os.getenv("CDP_API_KEY_SECRET"),
wallet_secret=os.getenv("CDP_WALLET_SECRET"),
network_id=network_id,
address=wallet_address,
# Only include idempotency_key if we need to create a new wallet
idempotency_key=(os.getenv("IDEMPOTENCY_KEY") if not wallet_address else None),
)

# Initialize the agent and get the wallet provider
agent_executor, wallet_provider = initialize_agent(config)

# Save the wallet data after successful initialization
new_wallet_data = {
"address": wallet_provider.get_address(),
"network_id": network_id,
"created_at": time.strftime("%Y-%m-%d %H:%M:%S")
if not wallet_data
else wallet_data.get("created_at"),
}

with open(wallet_file, "w") as f:
json.dump(new_wallet_data, f, indent=2)
print(f"Wallet data saved to {wallet_file}")

return agent_executor


# Autonomous Mode
async def run_autonomous_mode(agent_executor: AssistantAgent, interval=10) -> None:
"""Run the autonomous mode of the AssistantAgent with a specified interval between actions.

Args:
agent_executor (AssistantAgent): The agent responsible for executing tasks autonomously.
interval (int, optional): Time in seconds to wait between consecutive autonomous actions. Defaults to 10.

"""
print("Starting autonomous mode...")
while True:
try:
# Provide instructions autonomously
thought = (
"Be creative and do something interesting on the blockchain. "
"Choose an action or set of actions and execute it that highlights your abilities."
)

# Run agent in autonomous mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=thought, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

# Wait before the next action
await asyncio.sleep(interval)

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Chat Mode
async def run_chat_mode(agent_executor: AssistantAgent) -> None:
"""Run the assistant agent in chat mode.

Args:
agent_executor (AssistantAgent): The agent executor responsible for handling the
chatbot functionality and running tasks based on user input.

"""
print("Starting chat mode... Type 'exit' to end.")
while True:
try:
user_input = input("\nPrompt: ")
if user_input.lower() == "exit":
break

# Run agent with the user's input in chat mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=user_input, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Mode Selection
def choose_mode():
"""Prompt the user to select a mode of operation from the available options.

Returns
-------
str
The selected mode, either "chat" or "auto".

"""
while True:
print("\nAvailable modes:")
print("1. chat - Interactive chat mode")
print("2. auto - Autonomous action mode")

choice = input("\nChoose a mode (enter number or name): ").lower().strip()
if choice in ["1", "chat"]:
return "chat"
elif choice in ["2", "auto"]:
return "auto"
print("Invalid choice. Please try again.")


async def main():
"""Start the chatbot agent."""
# Load environment variables
load_dotenv()

# Set up the agent
agent_executor = setup()

# Run the agent in the selected mode
mode = choose_mode()
if mode == "chat":
await run_chat_mode(agent_executor=agent_executor)
elif mode == "auto":
await run_autonomous_mode(agent_executor=agent_executor)


if __name__ == "__main__":
print("Starting Agent...")
asyncio.run(main())
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions python/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,6 +34,12 @@ PydanticAI extension of AgentKit. Enables agentic workflows to interact with onc

See [AgentKit PydanticAI](./framework-extensions/pydantic-ai/README.md) to get started!

#### `coinbase-agentkit-autogen`

Microsoft Autogen extension of AgentKit. Enables agentic workflows to interact with onchain actions.

See [AgentKit Autogen](./framework-extensions/autogen/README.md)

### `create-onchain-agent`

A quickstart CLI tool to scaffold out a chatbot using Coinbase AgentKit. Runnable via `pipx run create-onchain-agent`.
Expand Down
8 changes: 8 additions & 0 deletions python/examples/autogen-cdp-chatbot/.env.local
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
# Required
CDP_API_KEY_ID=
CDP_API_KEY_SECRET=
CDP_WALLET_SECRET=
OPENAI_API_KEY=

# Optional with defaults
NETWORK_ID=base-sepolia
29 changes: 29 additions & 0 deletions python/examples/autogen-cdp-chatbot/Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
ifneq (,$(wildcard ./.env))
include .env
endif

export

.PHONY: install
install:
uv sync

.PHONY: run
run:
uv run chatbot.py

.PHONY: format
format:
uv run ruff format .

.PHONY: format-check
format-check:
uv run ruff format . --check

.PHONY: lint
lint:
uv run ruff check .

.PHONY: lint-fix
lint-fix:
uv run ruff check . --fix
50 changes: 50 additions & 0 deletions python/examples/autogen-cdp-chatbot/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
# CDP Agentkit Autogen Extension Examples - Chatbot Python

This example demonstrates an agent setup as a terminal style chatbot using Microsoft Autogen integration with CDP Agentkit actions.

## Ask the chatbot to engage in the Web3 ecosystem!

- "What is the price of BTC?"
- "Request some test tokens from the faucet"
- "What are my CDP account details?"
- "Transfer a portion of your ETH to a random address"
- "Deploy an NFT that will go super viral!"
- "Deploy an ERC-20 token with total supply 1 billion"

## Requirements

- Python 3.10+
- uv for package management and tooling
- [uv Installation Instructions](https://github.com/astral-sh/uv?tab=readme-ov-file#installation)
- [CDP API Key](https://portal.cdp.coinbase.com/access/api)
- [OpenAI API Key](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key)

### Checking Python Version

Before using the example, ensure that you have the correct version of Python installed. The example requires Python 3.10 or higher. You can check your Python version by running:

```bash
python --version
uv --version
```

## Installation

```bash
make install
```

## Run the Chatbot

### Env

Rename .env.local to .env and ensure the following var are set:

- "CDP_API_KEY_ID"
- "CDP_API_KEY_SECRET"
- "CDP_WALLET_SECRET" # This is the wallet secret for the wallet you want to use for the chatbot
- "OPENAI_API_KEY"

```bash
make run
```
270 changes: 270 additions & 0 deletions python/examples/autogen-cdp-chatbot/chatbot.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
import asyncio
import json
import os
import time

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import BaseChatMessage, TextMessage
from autogen_core.memory import ListMemory
from autogen_ext.models.openai import OpenAIChatCompletionClient
from coinbase_agentkit import (
AgentKit,
AgentKitConfig,
CdpEvmWalletProvider,
CdpEvmWalletProviderConfig,
cdp_api_action_provider,
erc20_action_provider,
pyth_action_provider,
wallet_action_provider,
weth_action_provider,
x402_action_provider,
)
from coinbase_agentkit_autogen.autogen_tools import get_autogen_tools
from dotenv import load_dotenv


def initialize_agent(
config: CdpEvmWalletProviderConfig,
) -> tuple[AssistantAgent, CdpEvmWalletProvider]:
"""Initialize the agent with CDP Agentkit.

Args:
config: Configuration for the CDP EVM Server Wallet Provider

Returns:
tuple[Agent, CdpEvmServerWalletProvider]: The initialized agent and wallet provider

"""
# Initialize the language model
model_client = OpenAIChatCompletionClient(
model="gpt-4o-mini",
)

# Initialize the wallet provider with the config
wallet_provider = CdpEvmWalletProvider(
CdpEvmWalletProviderConfig(
api_key_id=config.api_key_id, # CDP API Key ID
api_key_secret=config.api_key_secret, # CDP API Key Secret
wallet_secret=config.wallet_secret, # CDP Wallet Secret
network_id=config.network_id, # Network ID - Optional, will default to 'base-sepolia'
address=config.address, # Wallet Address - Optional, will trigger idempotency flow if not provided
idempotency_key=config.idempotency_key, # Idempotency Key - Optional, seeds generation of a new wallet
rpc_url=config.rpc_url, # Optional RPC URL override
)
)

# Create AgentKit instance with wallet and action providers
agentkit = AgentKit(
AgentKitConfig(
wallet_provider=wallet_provider,
action_providers=[
cdp_api_action_provider(),
erc20_action_provider(),
pyth_action_provider(),
wallet_action_provider(),
weth_action_provider(),
x402_action_provider(),
],
)
)

# Get tools for the agent
tools = get_autogen_tools(agentkit)

# Set up conversation memory
memory = ListMemory()

# Set up Autogen Assistant Agent
agent = AssistantAgent(
name="assistant",
model_client=model_client,
reflect_on_tool_use=True,
tools=tools,
memory=[memory],
max_tool_iterations=3,
system_message=(
"You are a helpful agent that can interact onchain using the Coinbase Developer Platform AgentKit. "
"You are empowered to interact onchain using your tools. If you ever need funds, you can request "
"them from the faucet if you are on network ID 'base-sepolia'. If not, you can provide your wallet "
"details and request funds from the user. Before executing your first action, get the wallet details "
"to see what network you're on. If there is a 5XX (internal) HTTP error code, ask the user to try "
"again later. If someone asks you to do something you can't do with your currently available tools, "
"you must say so, and encourage them to implement it themselves using the CDP SDK + Agentkit, "
"recommend they go to docs.cdp.coinbase.com for more information. Be concise and helpful with your "
"responses. Refrain from restating your tools' descriptions unless it is explicitly requested."
),
)

# Create and return the agent and wallet provider
return agent, wallet_provider


def setup() -> AssistantAgent:
"""Set up the agent with persistent wallet storage.

Returns:
AssistantAgent: The initialized agent used for handling wallet interactions and
executing associated operations.

"""
# Configure network and file path
network_id = os.getenv("NETWORK_ID", "base-sepolia")
wallet_file = f"wallet_data_{network_id.replace('-', '_')}.txt"

# Load existing wallet data if available
wallet_data = {}
if os.path.exists(wallet_file):
try:
with open(wallet_file) as f:
wallet_data = json.load(f)
print(f"Loading existing wallet from {wallet_file}")
except json.JSONDecodeError:
print(f"Warning: Invalid wallet data for {network_id}")
wallet_data = {}

# Determine wallet address using priority order
wallet_address = (
wallet_data.get("address") # First priority: Saved wallet file
or os.getenv("ADDRESS") # Second priority: ADDRESS env var
or None # Will trigger idempotency flow if needed
)

# Create the wallet provider config
config = CdpEvmWalletProviderConfig(
api_key_id=os.getenv("CDP_API_KEY_ID"),
api_key_secret=os.getenv("CDP_API_KEY_SECRET"),
wallet_secret=os.getenv("CDP_WALLET_SECRET"),
network_id=network_id,
address=wallet_address,
# Only include idempotency_key if we need to create a new wallet
idempotency_key=(os.getenv("IDEMPOTENCY_KEY") if not wallet_address else None),
)

# Initialize the agent and get the wallet provider
agent_executor, wallet_provider = initialize_agent(config)

# Save the wallet data after successful initialization
new_wallet_data = {
"address": wallet_provider.get_address(),
"network_id": network_id,
"created_at": time.strftime("%Y-%m-%d %H:%M:%S")
if not wallet_data
else wallet_data.get("created_at"),
}

with open(wallet_file, "w") as f:
json.dump(new_wallet_data, f, indent=2)
print(f"Wallet data saved to {wallet_file}")

return agent_executor


# Autonomous Mode
async def run_autonomous_mode(agent_executor: AssistantAgent, interval=10) -> None:
"""Run the autonomous mode of the AssistantAgent with a specified interval between actions.

Args:
agent_executor (AssistantAgent): The agent responsible for executing tasks autonomously.
interval (int, optional): Time in seconds to wait between consecutive autonomous actions. Defaults to 10.

"""
print("Starting autonomous mode...")
while True:
try:
# Provide instructions autonomously
thought = (
"Be creative and do something interesting on the blockchain. "
"Choose an action or set of actions and execute it that highlights your abilities."
)

# Run agent in autonomous mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=thought, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

# Wait before the next action
await asyncio.sleep(interval)

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Chat Mode
async def run_chat_mode(agent_executor: AssistantAgent) -> None:
"""Run the assistant agent in chat mode.

Args:
agent_executor (AssistantAgent): The agent executor responsible for handling the
chatbot functionality and running tasks based on user input.

"""
print("Starting chat mode... Type 'exit' to end.")
while True:
try:
user_input = input("\nPrompt: ")
if user_input.lower() == "exit":
break

# Run agent with the user's input in chat mode
async for chunk in agent_executor.run_stream(
task=TextMessage(content=user_input, source="User"), output_task_messages=False
):
if isinstance(chunk, BaseChatMessage):
print("\n-------------------")
print(chunk.to_text())
print("-------------------")

except KeyboardInterrupt:
print("Goodbye Agent!")
await agent_executor._model_client.close()
return


# Mode Selection
def choose_mode():
"""Prompt the user to select a mode of operation from the available options.

Returns
-------
str
The selected mode, either "chat" or "auto".

"""
while True:
print("\nAvailable modes:")
print("1. chat - Interactive chat mode")
print("2. auto - Autonomous action mode")

choice = input("\nChoose a mode (enter number or name): ").lower().strip()
if choice in ["1", "chat"]:
return "chat"
elif choice in ["2", "auto"]:
return "auto"
print("Invalid choice. Please try again.")


async def main():
"""Start the chatbot agent."""
# Load environment variables
load_dotenv()

# Set up the agent
agent_executor = setup()

# Run the agent in the selected mode
mode = choose_mode()
if mode == "chat":
await run_chat_mode(agent_executor=agent_executor)
elif mode == "auto":
await run_autonomous_mode(agent_executor=agent_executor)


if __name__ == "__main__":
print("Starting Agent...")
asyncio.run(main())
Loading
Loading