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
18 changes: 15 additions & 3 deletions python/create-onchain-agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,20 @@ pipx run create-onchain-agent

This command will guide you through setting up an onchain agent project by prompting for necessary configuration options.

### Beginner Mode

If you are a beginner to web3 agents, we recommend running the command with the `beginner` flag:

```sh
pipx run create-onchain-agent --beginner
```

This will create a simplified chatbot with our recommended configurations, so you can get started quickly, without having to worry about the underlying details.

## Features

- **Guided setup**: Interactive prompts help configure the project.
- **Supports multiple agent frameworks**.
- **Supports multiple blockchain networks**.
- **Select your preferred wallet provider**.
- **Automates environment setup**.
Expand All @@ -41,9 +52,10 @@ The CLI will prompt you for the following details:

1. **Project Name**: The name of your new onchain agent project.
2. **Package Name**: The Python package name (auto-formatted if needed).
3. **Network**: Choose from available blockchain networks.
4. **Chain ID**: Specify if using a custom network.
5. **Wallet Provider**: Select a preferred method for wallet management.
3. **Framework**: Choose from available agent frameworks.
4. **Network**: Choose from available blockchain networks.
5. **Chain ID**: Specify if using a custom network.
6. **Wallet Provider**: Select a preferred method for wallet management.

After answering the prompts, the CLI will:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added --beginner flag
1 change: 1 addition & 0 deletions python/create-onchain-agent/changelog.d/557.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added OpenAI Agents SDK support
216 changes: 173 additions & 43 deletions python/create-onchain-agent/create_onchain_agent/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

# GitHub repo and folder path
GITHUB_ZIP_URL = "https://github.com/coinbase/agentkit/archive/refs/heads/main.zip"
TEMPLATE_SUBDIR = "agentkit-main/python/create-onchain-agent/templates/chatbot"
TEMPLATES_SUBDIR = "agentkit-main/python/create-onchain-agent/templates"
LOCAL_CACHE_DIR = Path(platformdirs.user_cache_dir("create-onchain-agent"))

console = Console()
Expand Down Expand Up @@ -55,6 +55,12 @@
("polygon-mumbai", "Polygon Mumbai"),
]

# Framework constants
FRAMEWORKS = [
("Langchain", "langchain"),
("OpenAI Agents SDK", "openai_agents"),
]

CDP_SUPPORTED_NETWORKS = {
"base-mainnet",
"base-sepolia",
Expand All @@ -67,19 +73,20 @@
VALID_PACKAGE_NAME_REGEX = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$")


def get_template_path(template_path: str | None = None) -> str:
def get_template_path(template_name: str, templates_path: str | None = None) -> str:
"""Get the template path either from a local directory or downloaded from GitHub.

Args:
template_path: Optional path to local template directory
templates_path: Optional path to local template directory
template_name: The name of the template to get

Returns:
str: Path to the template directory

"""
if template_path:
if templates_path:
# Use provided template path
local_template_path = Path(template_path)
local_template_path = Path(f"{templates_path}/{template_name}")
if not local_template_path.exists():
raise FileNotFoundError(
f"Template path not found at {local_template_path}. "
Expand Down Expand Up @@ -107,9 +114,9 @@ def get_template_path(template_path: str | None = None) -> str:
with zipfile.ZipFile(zip_path, "r") as zip_ref:
zip_ref.extractall(LOCAL_CACHE_DIR)

template_path = LOCAL_CACHE_DIR / TEMPLATE_SUBDIR
template_path = LOCAL_CACHE_DIR / TEMPLATES_SUBDIR / template_name
if not template_path.exists():
raise FileNotFoundError(f"Template path {TEMPLATE_SUBDIR} not found in ZIP.")
raise FileNotFoundError(f"Template path {TEMPLATES_SUBDIR}/{template_name} not found in ZIP.")

# Move extracted template to a stable path
shutil.move(str(template_path), str(extract_path))
Expand All @@ -129,23 +136,8 @@ def get_network_choices(network_type: str) -> list:
)
]


@click.command()
@click.option("--template", type=str, help="Path to local template directory", default=None)
def create_project(template):
"""Create a new onchain agent project with interactive prompts."""
ascii_art = """
█████ ██████ ███████ ███ ██ ████████ ██ ██ ██ ████████
██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██
███████ ██ ███ █████ ██ ██ ██ ██ █████ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██████ ███████ ██ ████ ██ ██ ██ ██ ██

Giving every AI agent a crypto wallet
"""

console.print(f"[blue]{ascii_art}[/blue]")

def create_advanced_project(templates_path: str | None = None):
"""Create a new onchain agent project with advanced setup."""
# Prompt for project name (default: "onchain-agent")
project_name = (
questionary.text("Enter your project name:", default="onchain-agent", style=custom_style)
Expand Down Expand Up @@ -175,6 +167,23 @@ def create_project(template):
else:
package_name = suggested_package_name

# Choose framework
framework_choices = [
name + (" (default)" if id == "langchain" else "")
for name, id in FRAMEWORKS
]
framework_name = questionary.select(
"Choose your agent framework:",
choices=framework_choices,
default="Langchain (default)",
style=custom_style,
).ask()

# Remove " (default)" suffix if present
framework_name = framework_name.replace(" (default)", "")
# Look up the framework ID from the name
framework = next(id for name, id in FRAMEWORKS if name == framework_name)

# Choose network type
network_type = questionary.select(
"Choose network type:",
Expand Down Expand Up @@ -260,6 +269,7 @@ def create_project(template):
"_package_name": package_name,
"_network": network,
"_wallet_provider": wallet_provider,
"_framework": framework,
}

if chain_id:
Expand All @@ -268,32 +278,152 @@ def create_project(template):
copier_data["_rpc_url"] = rpc_url

try:
template_path = get_template_path(template)
template_path = get_template_path("chatbot", templates_path)
run_copy(template_path, project_path, data=copier_data)

console.print(
f"[bold blue]Successfully created your AgentKit project in {project_path}[/bold blue]"
)

console.print("\n[bold]What's Next?[/bold]")

console.print("To get started, run the following commands:")
console.print(f" [gray]- cd {project_name}[/gray]")
console.print(" [gray]- poetry install[/gray]")
console.print(" [dim]- # Open .env.local and configure your API keys[/dim]")
console.print(" [gray]- mv .env.local .env[/gray]")
console.print(" [gray]- poetry run python chatbot.py[/gray]")

console.print("\n[bold]Learn more[/bold]")
console.print(" - Checkout the docs")
console.print(" [blue]https://docs.cdp.coinbase.com/agentkit/docs/welcome[/blue]")
console.print(" - Visit the repo")
console.print(" [blue]https://github.com/coinbase/agentkit[/blue]")
console.print(" - Join the community")
console.print(" [blue]https://discord.gg/CDP[/blue]\n")

except FileNotFoundError as e:
console.print(f"[red]Error: {e!s}[/red]")
return

console.print(
f"[bold blue]Successfully created your AgentKit project in {project_path}[/bold blue]"
def create_beginner_project(templates_path: str | None = None):
"""Create a new onchain agent project with simplified setup."""
# Prompt for project name (default: "onchain-agent")
project_name = (
questionary.text("Enter your project name:", default="onchain-agent", style=custom_style)
.ask()
.strip()
)

console.print("\n[bold]What's Next?[/bold]")

console.print("To get started, run the following commands:")
console.print(f" [gray]- cd {project_name}[/gray]")
console.print(" [gray]- poetry install[/gray]")
console.print(" [dim]- # Open .env.local and configure your API keys[/dim]")
console.print(" [gray]- mv .env.local .env[/gray]")
console.print(" [gray]- poetry run python chatbot.py[/gray]")

console.print("\n[bold]Learn more[/bold]")
console.print(" - Checkout the docs")
console.print(" [blue]https://docs.cdp.coinbase.com/agentkit/docs/welcome[/blue]")
console.print(" - Visit the repo")
console.print(" [blue]https://github.com/coinbase/agentkit[/blue]")
console.print(" - Join the community")
console.print(" [blue]https://discord.gg/CDP[/blue]\n")
project_path = os.path.join(os.getcwd(), project_name)

if os.path.exists(project_path):
console.print(f"[red]Error: Directory '{project_name}' already exists.[/red]")
return None, None

# Attempt to generate a valid package name
suggested_package_name = project_name.replace("-", "_").replace(" ", "_")

if not VALID_PACKAGE_NAME_REGEX.match(suggested_package_name):
# Prompt user if the generated package name is invalid
package_name = (
questionary.text(
"Enter a valid Python package name (letters, numbers, underscores only):",
style=custom_style,
)
.ask()
.strip()
)
else:
package_name = suggested_package_name

framework_choices = [
name + (" (default)" if id == "langchain" else "")
for name, id in FRAMEWORKS
]
framework_name = questionary.select(
"Choose your agent framework:",
choices=framework_choices,
default="Langchain (default)",
style=custom_style,
).ask()

# Remove " (default)" suffix if present
framework_name = framework_name.replace(" (default)", "")
framework = next(id for name, id in FRAMEWORKS if name == framework_name)

console.print(f"\n[blue]Creating your onchain agent project: {project_name}[/blue]")

copier_data = {
"_project_name": project_name,
"_package_name": package_name,
"_framework": framework,
}

try:
template_path = get_template_path("beginner", templates_path)
run_copy(template_path, project_path, data=copier_data)

console.print(
f"[bold blue]🎉 Successfully created your AI agent in {project_path}![/bold blue]"
)

console.print("\n[bold]What makes this agent special?[/bold]")
console.print(
"[gray]Your AI agent comes with a secure digital wallet on the Base Sepolia network - "
"a network designed for development and testing with no financial risk. Your agent can:[/gray]\n"
"[dim] • Check wallet balances\n"
" • Send and receive tokens\n"
" • Make secure financial decisions\n[/dim]"
"\n[gray]When you're ready to move to Base Mainnet, your agent will get $X in free transaction fees. "
"You can change networks anytime by updating the NETWORK_ID in your .env file.[/gray]"
)

console.print("\n[bold]What's next?[/bold]")
console.print("To get started, run the following commands:")
console.print(f" [gray]- cd {project_name}[/gray]")
console.print(" [gray]- poetry install[/gray]")
console.print(" [dim]- # Open .env.local and configure your API keys[/dim]")
console.print(" [gray]- mv .env.local .env[/gray]")
console.print(" [gray]- poetry run python chatbot.py[/gray]")

console.print("\n[bold]Learn more[/bold]")
console.print(" - Checkout the docs")
console.print(" [blue]https://docs.cdp.coinbase.com/agentkit/docs/welcome[/blue]")
console.print(" - Visit the repo")
console.print(" [blue]https://github.com/coinbase/agentkit[/blue]")
console.print(" - Join the community")
console.print(" [blue]https://discord.gg/CDP[/blue]\n")

except FileNotFoundError as e:
console.print(f"[red]Error: {e!s}[/red]")
return

@click.command()
@click.option("--templates-path", type=str, help="Path to local template directory", default=None)
@click.option(
"--beginner",
is_flag=True,
help="Use beginner mode with simplified setup",
)
def create_project(templates_path, beginner):
"""Create a new onchain agent project with interactive prompts."""
ascii_art = """
█████ ██████ ███████ ███ ██ ████████ ██ ██ ██ ████████
██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██
███████ ██ ███ █████ ██ ██ ██ ██ █████ ██ ██
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██████ ███████ ██ ████ ██ ██ ██ ██ ██

Giving every AI agent a crypto wallet
"""

console.print(f"[blue]{ascii_art}[/blue]")

if beginner:
create_beginner_project(templates_path)
else:
create_advanced_project(templates_path)


if __name__ == "__main__":
Expand Down
44 changes: 44 additions & 0 deletions python/create-onchain-agent/templates/beginner/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# Virtual Environment
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Poetry
poetry.lock

# IDE
.idea/
.vscode/
*.swp
*.swo
.DS_Store

# Project specific
wallet_data*.txt
.env.local
Loading