Local CLI Testing
Test your agents locally during development without the control plane
While building your agent, you can test skills and reasoners locally using CLI commands. This provides fast feedback during development without needing to run the control plane or make HTTP requests.
Quick Start
Given a simple agent:
from agentfield import Agent
app = Agent(node_id="hello-world")
@app.skill()
def get_greeting(name: str) -> dict:
return {"message": f"Hello, {name}!"}
@app.reasoner
async def say_hello(name: str) -> dict:
greeting = get_greeting(name)
return greeting
if __name__ == "__main__":
app.serve()You can test it locally with CLI commands:
# Execute a function
python main.py call say_hello --name Alice
# List all available functions
python main.py list
# Interactive shell
python main.py shellCLI mode runs your agent locally without the control plane. This means no workflow tracking, no DIDs, no observability - just fast function execution for testing.
CLI Commands
call - Execute Functions
Execute any registered skill or reasoner with automatic argument parsing.
Basic Usage:
python main.py call <function_name> --arg1 value1 --arg2 value2Examples:
# Simple string argument
python main.py call say_hello --name Alice
# Multiple arguments
python main.py call process_ticket --text "Bug report" --priority high
# Numeric arguments
python main.py call calculate_metrics --threshold 0.85 --max_items 100
# Boolean arguments
python main.py call analyze_data --include_metadata true --verbose falseComplex Arguments (JSON):
For dict, list, or complex objects, pass JSON strings:
# Dictionary argument
python main.py call process_data --config '{"mode": "fast", "retries": 3}'
# List argument
python main.py call batch_process --items '[1, 2, 3, 4, 5]'
# Nested structures
python main.py call analyze --data '{"user": {"id": 123, "tags": ["premium"]}}'Output:
Results are printed as formatted JSON:
{
"message": "Hello, Alice!"
}list - Discover Functions
List all available skills and reasoners with their signatures and descriptions.
python main.py listOutput:
📋 Agent: hello-world
Skills (deterministic):
• get_greeting(name: str) -> dict
No description
Reasoners (AI-powered):
• say_hello(name: str) -> dict
No descriptionAdd docstrings to your functions to see helpful descriptions in the list output.
With Docstrings:
@app.reasoner
async def analyze_sentiment(text: str) -> dict:
"""Analyze the sentiment of the given text using AI."""
return await app.ai(
system="Analyze sentiment as positive, negative, or neutral",
user=text
)$ python main.py list
Reasoners (AI-powered):
• analyze_sentiment(text: str) -> dict
Analyze the sentiment of the given text using AI.shell - Interactive Mode
Launch an interactive Python shell with all functions pre-loaded in the namespace.
python main.py shellOutput:
🚀 Agent Shell: hello-world
Available functions: ['agent', 'get_greeting', 'say_hello']
Tip: Use 'await say_hello(name="Alice")' for async functions
In [1]:Usage in Shell:
# Call skills directly
In [1]: get_greeting(name="Bob")
Out[1]: {'message': 'Hello, Bob!'}
# Call async reasoners with await
In [2]: await say_hello(name="Charlie")
Out[2]: {'message': 'Hello, Charlie!'}
# Access the agent instance
In [3]: agent.node_id
Out[3]: 'hello-world'The shell mode requires IPython. Install it with: pip install ipython
CLI vs Server Mode
The same Python file automatically detects which mode to run:
# CLI commands trigger local testing mode
python main.py call say_hello --name Alice
python main.py list
python main.py shellCharacteristics:
- ✅ Fast local execution
- ✅ No setup required
- ✅ Immediate feedback
- ❌ No control plane connection
- ❌ No workflow tracking
- ❌ No DIDs or verifiable credentials
- ❌ No observability or monitoring
Use for: Development, testing, debugging
# No CLI commands = server mode
python main.pyCharacteristics:
- ✅ Full control plane integration
- ✅ Workflow tracking and DAGs
- ✅ DIDs and verifiable credentials
- ✅ Observability and monitoring
- ✅ Cross-agent communication
- ✅ Production-ready
Use for: Production deployment, distributed systems
Common Testing Workflows
1. Rapid Iteration
Test changes immediately without restarting servers:
# Edit your code
vim main.py
# Test the change
python main.py call my_function --arg value
# Iterate
vim main.py
python main.py call my_function --arg value2. Debugging with Shell
Use the interactive shell to explore behavior:
python main.py shell# Test different inputs
In [1]: await analyze_sentiment(text="I love this!")
Out[1]: {'sentiment': 'positive', 'confidence': 0.95}
In [2]: await analyze_sentiment(text="This is terrible")
Out[2]: {'sentiment': 'negative', 'confidence': 0.92}
# Inspect intermediate results
In [3]: data = get_user_data(user_id=123)
In [4]: data
Out[4]: {'id': 123, 'name': 'Alice', 'email': 'alice@example.com'}3. Testing Before Deployment
Validate your agent works before deploying:
# Test all critical functions
python main.py call process_order --order_id 12345
python main.py call calculate_total --items '[{"price": 10}, {"price": 20}]'
python main.py call send_notification --user_id 123 --message "Test"
# List to verify all functions are registered
python main.py list
# Deploy when ready
python main.py # Starts server modeType Hint Support
CLI commands automatically parse arguments based on function type hints:
from pydantic import BaseModel
class UserInput(BaseModel):
name: str
age: int
tags: list[str]
@app.skill()
def process_user(user: UserInput) -> dict:
return {
"processed": True,
"name": user.name,
"age": user.age,
"tag_count": len(user.tags)
}# Pydantic models accept JSON
python main.py call process_user --user '{
"name": "Alice",
"age": 30,
"tags": ["premium", "verified"]
}'Supported Types:
str- String valuesint- Integer valuesfloat- Floating point valuesbool- Boolean values (true/false)dict- JSON objectslist- JSON arrays- Pydantic models - JSON objects validated against schema
Limitations
CLI mode is designed for development and testing only. It does not provide:
❌ No Control Plane Features:
- No workflow tracking or DAG visualization
- No execution IDs or workflow IDs
- No DIDs (Decentralized Identifiers)
- No verifiable credentials
- No observability or monitoring
- No cross-agent communication via
app.call()
❌ No Production Features:
- No HTTP endpoints
- No webhook callbacks
- No async execution with polling
- No SSE (Server-Sent Events)
- No authentication or authorization
Always use server mode for production deployments. CLI mode is strictly for local testing during development.
When to Use Each Mode
Use CLI Mode When:
- 🔧 Developing new skills or reasoners
- 🐛 Debugging function behavior
- ✅ Testing changes before deployment
- 🚀 Validating agent logic locally
- 📝 Exploring function signatures
Use Server Mode When:
- 🌐 Deploying to production
- 📊 Need workflow tracking and observability
- 🔗 Building distributed multi-agent systems
- 🔐 Require DIDs and verifiable credentials
- 📈 Need monitoring and analytics
Example: Complete Development Workflow
# main.py
from agentfield import Agent
from pydantic import BaseModel
app = Agent(node_id="support-agent")
class TicketAnalysis(BaseModel):
category: str
priority: str
estimated_time: int
@app.reasoner
async def analyze_ticket(ticket_text: str) -> TicketAnalysis:
"""Analyze support ticket and categorize it."""
return await app.ai(
system="Analyze support tickets",
user=ticket_text,
schema=TicketAnalysis
)
if __name__ == "__main__":
app.serve()Development Phase:
# Test during development
python main.py call analyze_ticket --ticket_text "Login button not working"
# Output:
# {
# "category": "technical",
# "priority": "high",
# "estimated_time": 30
# }
# Iterate and test again
python main.py call analyze_ticket --ticket_text "How do I reset my password?"
# Verify all functions
python main.py listProduction Deployment:
# Deploy with control plane
python main.py
# Now accessible via HTTP with full observability
curl -X POST http://localhost:8080/api/v1/execute/support-agent.analyze_ticket \
-H "Content-Type: application/json" \
-d '{"input": {"ticket_text": "Login button not working"}}'Related
- Agent Class - Core agent initialization
- @app.reasoner - Define AI-powered functions
- @app.skill() - Create deterministic skills
- app.serve() - Production server mode