Best Practices
Guidelines for building production-quality LeafMesh systems.
Agent Design
Keep Agents Focused
Each agent should have a single responsibility:
# Good: focused agents
agents:
classifier:
name: "classifier"
model: "gpt-4o-mini" # required — the SDK never picks one for you
prompt: "Classify the request by category and urgency."
yields:
category: "string"
urgency: "number"
resolver:
name: "resolver"
model: "gpt-4o-mini"
prompt: "Resolve the technical issue."
yields:
solution: "string"
confidence: "number"# Bad: agent doing too much
agents:
do_everything:
name: "do_everything"
prompt: "Classify the request, resolve it, write a response, and log it."
yields:
category: "string"
urgency: "number"
solution: "string"
response: "string"
log_entry: "string"Use Appropriate Agent Types
| Task | Agent Type |
|---|---|
| Classification, analysis, content generation | LLM |
| Data validation, calculations, API calls | Programmatic |
| Approvals, quality review | Human |
| Monitoring, reports, maintenance | Scheduled |
Design Clear Yields Schemas
# Good: clear, typed outputs
yields:
category: "string"
confidence: "number"
is_urgent: "boolean"
# Avoid: vague or overly complex schemas
yields:
result: "string" # Too vague
data: "string" # What data?Configuration
Use One Agency per Environment
The configuration lives in each agency's store, so give each environment its own agency, each with its own versioned configuration:
# Development agency
agents:
classifier:
name: "classifier"
model: "gpt-4o-mini" # Cheaper for development
# Production agency
agents:
classifier:
name: "classifier"
model: "gpt-4o" # More capable for productionKeep one .env per environment; it names the agency and its store (from 2.4.482 the store is set only in .env, never in the YAML):
# .env (development)
LEAFMESH_AGENCY_NAME=support-dev
LEAFMESH_STORE=redis
REDIS_HOST=localhost
# .env (production, Redis Cluster)
LEAFMESH_AGENCY_NAME=support-prod
LEAFMESH_STORE=redis
REDIS_CLUSTER_NODES=redis-1:6379,redis-2:6379,redis-3:6379Set Appropriate Token Limits
agents:
classifier:
name: "classifier"
max_tokens: 500 # Short classification output
writer:
name: "writer"
max_tokens: 2000 # Longer content output
analyzer:
name: "analyzer"
max_tokens: 1000 # Medium analysis outputConfigure Sensible Timeouts
agents:
human_reviewer:
name: "human_reviewer"
timeout: 300 # 5 minutes for human response
manager:
coordination_rules:
max_agent_calls: 10 # Prevent runaway chainsIntelligence Functions
Keep Business Logic in Intelligence Functions
async def processor(llm_response, input_data, context):
# Business rules belong here, not in prompts
if llm_response.get("amount", 0) > 10000:
llm_response["requires_approval"] = True
return llm_responseUse Pre-Compose for Data Assembly
# Good: deterministic context before LLM
@pre_compose(context_processor=fetch_account_data)
async def specialist(llm_response, input_data, context):
return llm_response# Avoid: fetching data inside intelligence function
# (too late - LLM already ran without this context)
async def specialist(llm_response, input_data, context):
account = await fetch_account_data(...) # LLM didn't see this
return llm_responseRouting
Use Explicit Conditions
# Good: clear, specific conditions
can_call:
- agent: "specialist"
condition: "urgency >= 7 and category == 'technical'"
# Avoid: overly broad conditions
can_call:
- agent: "specialist"
condition: "true" # Everything routes hereDesign for Failure
Include fallback paths in your routing:
can_call:
- agent: "specialist"
condition: "confidence > 0.8"
- agent: "human_reviewer"
condition: "confidence <= 0.8" # Fallback for low confidenceAlways Bound Retry Back-Edges
Warning: Any
can_callthat routes back upstream (a retry loop, or a critic that loops to a writer) is a cycle. If its condition can stay true forever, the chain climbs until it hits themesh.max_chain_eventscap (default 50) and the session is stopped with aChainCapExceedederror — after burning real LLM spend.
Bound every such back-edge with a per-session exhaustion counter: count attempts in the agent's Python, yield a *_retry_exhausted boolean, gate the back-edge on it, and add a terminal route for the exhausted case. There is no once_per_session flag — the bounding is your job. See Coordination → Chain Cap & Bounding Cycles for the full pattern.
Monitoring
Check System Health Regularly
# Periodic health check
analytics = Studio's Dashboard (HTTP)
agent_stats = leafmesh.get_agent_stats()
cache_stats = Studio's Dashboard (HTTP)Monitor Error Rates
High error rates indicate configuration or provider issues. Check:
- Agent error rates via
leafmesh.get_agent_stats() - Provider availability
- Redis connectivity
Next Steps
- Agent Development — Agent building guide
- Testing Framework — Testing strategies
- Production Setup — Production deployment
LeafMesh — Development best practices