- Update workflow paths from docs/openclaw to docs/hermes - Rename skill prefixes from openclaw-* to hermes-* - Update agent skill references in refactoring and analysis docs - Rename OPENCLAW_AITBC_MASTERY_PLAN.md to reflect hermes branding - Update CLI examples and command references throughout documentation
15 KiB
AITBC CLI Architecture
This document describes the architecture of the AITBC CLI system, including component interactions, data flows, and extension points.
System Overview
The AITBC CLI follows a modular, layered architecture:
┌─────────────────────────────────────────────────────────┐
│ User Interface Layer │
│ (Command Line Interface) │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Parser Layer │
│ (Argument Parsing & Validation) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ wallet.py │ │ blockchain.py │ │ ai.py │ │
│ │ market.py │ │ network.py │ │ workflow.py │ │
│ │ ... │ │ ... │ │ ... │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Unified CLI Layer │
│ (Handler Registration & Dispatch) │
│ ┌────────────────────────────────────────────────────┐ │
│ │ unified_cli.py │ │
│ │ - Parser registration │ │
│ │ - Handler wrappers │ │
│ │ - Handler dispatch table │ │
│ └────────────────────────────────────────────────────┘ │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Handler Layer │
│ (Command Implementation) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ wallet.py │ │ ai.py │ │ system.py │ │
│ │ market.py │ │ blockchain.py │ │ ... │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Backend Services Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Blockchain │ │ Agent │ │ Marketplace │ │
│ │ RPC (8006) │ │ Coordinator │ │ Exchange │ │
│ │ │ │ (9001) │ │ (8001) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
Component Interactions
1. Parser Registration Flow
parsers/__init__.py
│
├── import all parser modules
│ ├── from . import wallet
│ ├── from . import blockchain
│ ├── from . import ai
│ └── ...
│
└── register_all(subparsers, ctx)
│
├── wallet.register(subparsers, ctx)
│ └── add_parser("wallet")
│ └── add_subparser("create", "list", ...)
│
├── blockchain.register(subparsers, ctx)
│ └── add_parser("blockchain")
│ └── add_subparser("info", "block", ...)
│
└── ai.register(subparsers, ctx)
└── add_parser("ai")
└── add_subparser("submit", "jobs", ...)
2. Command Execution Flow
User Input: "aitbc-cli ai submit hermes-trainee inference test 10"
│
▼
unified_cli.py:run_cli()
│
├── Parse arguments with argparse
│ └── parser.parse_args()
│ └── parsed_args = Namespace(...)
│
├── Get handler from parsed_args
│ └── handler = parsed_args.handler
│ └── handle_ai_submit
│
└── Execute handler
└── handler(parsed_args)
│
└── unified_cli.py:handle_ai_submit()
│
└── ai_handlers.handle_ai_submit()
│
├── Get coordinator URL
├── Build job request
├── HTTP POST to Agent Coordinator
└── Render result
3. Handler Pattern
Handler Wrapper (unified_cli.py)
│
├── def handle_ai_submit(args):
│ └── ai_handlers.handle_ai_submit(args, default_rpc_url, default_coordinator_url, first, read_password, render_mapping)
│ └── Passes context parameters
│
└── Handler Implementation (handlers/ai.py)
│
├── def handle_ai_submit(args, default_rpc_url, default_coordinator_url, first, read_password, render_mapping):
│ ├── Extract arguments
│ ├── Use context (RPC URL, coordinator URL)
│ ├── Make backend call
│ └── Render result
│
└── Return success/failure
Data Flow Diagrams
AI Job Submission Flow
User Command
│
▼
Parser (ai.py)
│
├── Parse: wallet, job_type, prompt, payment
├── Set default coordinator URL (9001)
└── Map to handler: handle_ai_submit
│
▼
Handler Wrapper (unified_cli.py)
│
├── Get context: default_rpc_url, default_coordinator_url
└── Call: ai_handlers.handle_ai_submit()
│
▼
Handler Implementation (handlers/ai.py)
│
├── Extract parameters from args
├── Build request:
│ {
│ "task_data": {
│ "model": model,
│ "prompt": prompt,
│ "parameters": {}
│ }
│ }
│
├── HTTP POST to http://localhost:9001/tasks/submit
├── Parse response
└── Render result to user
│
▼
Agent Coordinator Service (9001)
│
├── Receive job request
├── Queue job for processing
└── Return job ID to CLI
Blockchain Query Flow
User Command
│
▼
Parser (blockchain.py)
│
├── Parse: block height, RPC URL
├── Set default RPC URL (8006)
└── Map to handler: handle_blockchain_block
│
▼
Handler Wrapper (unified_cli.py)
│
├── Get context: default_rpc_url
└── Call: blockchain_handlers.handle_blockchain_block()
│
▼
Handler Implementation (handlers/blockchain.py)
│
├── Extract block height
├── Build request URL: http://localhost:8006/rpc/blocks/{height}
├── HTTP GET
├── Parse response
└── Render block data to user
│
▼
Blockchain RPC Service (8006)
│
├── Receive block request
├── Query blockchain state
└── Return block data
Marketplace Operation Flow
User Command
│
▼
Parser (market.py)
│
├── Parse: action (list, buy, sell), parameters
├── Set default marketplace URL (8001)
└── Map to handler: handle_market_listings
│
▼
Handler Wrapper (unified_cli.py)
│
├── Get context: default_marketplace_url
└── Call: market_handlers.handle_market_listings()
│
▼
Handler Implementation (handlers/market.py)
│
├── Build request URL: http://localhost:8001/listings
├── HTTP GET
├── Parse response
└── Render listings to user
│
▼
Marketplace Exchange API (8001)
│
├── Receive listings request
├── Query marketplace database
└── Return listings
Extension Points
1. Adding New Commands
Location: /opt/aitbc/cli/parsers/
Create new parser module following the pattern:
def register(subparsers, ctx):
parser = subparsers.add_parser("command", help="description")
parser.set_defaults(handler=ctx.handle_command)
Registration: Add to /opt/aitbc/cli/parsers/__init__.py
from . import mycommand
def register_all(subparsers, ctx):
mycommand.register(subparsers, ctx)
2. Adding New Handlers
Location: /opt/aitbc/cli/handlers/
Create handler module:
def handle_command(args, render_mapping):
# Implementation
pass
Registration: Add to /opt/aitbc/cli/unified_cli.py
from handlers import mycommand as mycommand_handlers
def handle_command(args):
mycommand_handlers.handle_command(args, render_mapping)
handlers = {
"handle_command": handle_command,
}
3. Adding Backend Service Integration
Pattern: Use HTTP requests to backend services
import requests
def handle_command(args, service_url, render_mapping):
url = f"{service_url}/endpoint"
response = requests.get(url, timeout=30)
if response.status_code == 200:
result = response.json()
render_mapping("Result:", result)
4. Adding Context Parameters
Location: /opt/aitbc/cli/unified_cli.py
Add context to handler wrapper:
def handle_command(args):
mycommand_handlers.handle_command(args, default_rpc_url, default_coordinator_url, render_mapping)
Handler signature:
def handle_command(args, default_rpc_url, default_coordinator_url, render_mapping):
# Use provided context
rpc_url = args.rpc_url or default_rpc_url
coordinator_url = args.coordinator_url or default_coordinator_url
Service Endpoints
Active Services
| Service | Port | Endpoint | Usage |
|---|---|---|---|
| Blockchain RPC | 8006 | /rpc/blocks/{height} |
Blockchain queries |
| Agent Coordinator | 9001 | /tasks/submit |
AI job submission |
| Marketplace Exchange | 8001 | /listings |
Marketplace operations |
Common Patterns
Agent Coordinator Integration:
coordinator_url = "http://localhost:9001"
job_data = {
"task_data": {
"model": model,
"prompt": prompt,
"parameters": {}
}
}
requests.post(f"{coordinator_url}/tasks/submit", json=job_data)
Blockchain RPC Integration:
rpc_url = "http://localhost:8006"
requests.get(f"{rpc_url}/rpc/blocks/latest")
Marketplace API Integration:
marketplace_url = "http://localhost:8001"
requests.get(f"{marketplace_url}/listings")
Error Handling Patterns
Graceful Degradation
def handle_command(args, render_mapping):
try:
# Try real backend call
result = backend_call()
render_mapping("Result:", result)
except Exception as e:
# Fall back to stub
print(f"Backend unavailable: {e}")
stub_result = {"status": "simulated"}
render_mapping("Result:", stub_result)
Non-Exiting Errors
def handle_command(args, render_mapping):
if not required_parameter:
print("Error: Missing required parameter")
return # Don't sys.exit(1)
Performance Considerations
HTTP Timeouts
response = requests.get(url, timeout=30) # 30 second timeout
Async Operations
For long-running operations, use stub handlers or background tasks:
def handle_long_operation(args, render_mapping):
result = {
"status": "submitted",
"operation_id": generate_id(),
"estimated_time": "5 minutes"
}
render_mapping("Operation:", result)
Security Considerations
Password Handling
def handle_command(args, read_password):
password = read_password(args.wallet, args.password_file)
# Use password for authentication
API Keys
Store API keys in environment variables or config files, not in code.
Input Validation
if not validate_input(args.input):
print("Error: Invalid input")
return
Testing Strategy
Unit Testing
Test handler functions in isolation:
def test_handle_command():
args = Namespace(option="value")
result = handle_command(args, mock_render_mapping)
assert result["status"] == "success"
Integration Testing
Test complete command flow:
/opt/aitbc/venv/bin/python /opt/aitbc/cli/unified_cli.py mycommand --option value
Monitoring & Debugging
Logging
Add logging to handlers:
import logging
logger = logging.getLogger(__name__)
def handle_command(args):
logger.info(f"Executing command with args: {args}")
Error Messages
Provide clear, actionable error messages:
print(f"Error: Failed to connect to service at {service_url}")
print(f" - Check if service is running")
print(f" - Verify URL is correct")