Production Setup

Production Setup

Configuration and operational practices for running LeafMesh in production.

Production Configuration

name: "production_system" architecture: "managed_mesh" manager: enabled: true model: "gpt-4o-mini" prompt: | # Optional: tell the Manager what success looks like Escalate if the same issue loops more than twice. coordination_rules: max_agent_calls: 10 agents: triage: name: "triage" model: "gpt-4o-mini" max_tokens: 500 temperature: 0.1 # ... agent configuration entry_points: - name: "api_request" target: "triage" description: "Primary API entry point"

This is the agency's configuration. It lives in the agency's store, not in a file: every Studio save is a new version (Studio's versions page lists each save with a diff, and make default restores one), and every pod runs the latest, applying a saved change within about 15 seconds.

From 2.4.482 the store is set only in .env, never in the YAML:

# .env LEAFMESH_AGENCY_NAME=production_system LEAFMESH_ENV_TOKEN=... # required from 2.4.507 LEAFMESH_VAULT_KEY=... # required from 2.4.507; the same on every pod LEAFMESH_WEBHOOK_SECRET=... # signed webhooks answer 503 without it (2.4.507) LEAFMESH_STORE=redis REDIS_PASSWORD=your-password REDIS_DEFAULT_TTL=3600 REDIS_SESSION_TTL=7200 # Setting this turns on cluster mode REDIS_CLUSTER_NODES=redis-1.internal:6379,redis-2.internal:6379,redis-3.internal:6379

Application Entry Point

import asyncio import signal from leafmesh import LeafMesh leafmesh = LeafMesh.from_store() async def main(): await leafmesh.start() # Graceful shutdown handler loop = asyncio.get_event_loop() for sig in (signal.SIGTERM, signal.SIGINT): loop.add_signal_handler(sig, lambda: asyncio.create_task(shutdown())) # Keep running until shutdown await asyncio.Event().wait() async def shutdown(): print("Shutting down gracefully...") await leafmesh.stop() asyncio.run(main())

Configuration Validation

LeafMesh validates all configuration at load time:

  • Type validation: Pydantic checks all field types
  • Required fields: Agents need name and prompt (LLM agents)
  • File size limits: YAML files checked against 10MB limit
  • YAML syntax: Parse errors reported with file location
  • Agent type validation: Different required fields per agent type
  • Encoding validation: UTF-8 enforced

Invalid configurations are rejected with descriptive errors before any components initialize.

Security Considerations

AST-Safe Condition Evaluation

YAML conditions use Python's ast module with whitelisted node types. No eval() anywhere.

Permission-Based Tool Access

Each agent's tools are declared in YAML. Unauthorized tool calls are rejected at the executor level.

Input Validation

The configuration is validated at load — syntax, required fields and types — and an inline key, token, password or address is refused, naming the field and the vault record to create.

Token Limits

Per-agent max_tokens and max_tool_calls_per_message prevent cost runaway.

Encryption in Transit

Redis traffic can run over TLS — set REDIS_SSL=true in .env and point REDIS_SSL_CA_CERTS at your CA bundle. Mutual TLS supported via REDIS_SSL_CERTFILE / REDIS_SSL_KEYFILE. See Redis Integration.

Webhook Replay Protection

Signed webhook endpoints (/webhook/{entry_point}, /callback/{agent_name}) bind each request to a fresh timestamp + nonce. Captured signed requests cannot be replayed beyond the configured skew window. See HITL Workflows for the signing recipe.

Trace Content Redacted by Default

With security.telemetry_redact_pii: true (the default since 2.4.480), each input and output content value in a trace is replaced whole with <redacted bytes:N>; names, models, tokens, cost, status, errors and timings stay visible. It is not per-word detection. Set it to false to keep content readable. Credentials are always masked either way. See Tracing.

Right to Erasure (GDPR Art. 17)

LeafMesh.erase_session(session_id) hard-deletes all persisted state for a session — session data, conversation history, agent outputs, mesh communications, channel mirrors, and pending callbacks. Emits a session.erased audit event with actor_id / request_id for SOC 2 CC7.2 traceability.

Secrets Stay Out of the Configuration

Keys, tokens, passwords, client ids and addresses (URLs, endpoints, hosts) are entered only in the vault, as records on Studio's Infrastructure page. The configuration names a record with connection: <name> (a zapier, composio or n8n tool block: vault_connection); an inline value, including a ${ENV:default} reference, is refused at load, naming the field and the record to create. If a named record does not exist yet, the agent that needs it is switched off with the reason and works as soon as the record exists — no restart. Model keys set in .env still work; from 2.4.492, a key that is also in the vault uses the vault's, with a warning to remove it from .env.

The Mesh's Own Sign-in Key

From 2.4.497 each mesh signs in to LeafCraft with its own identity: a key pair held in its own vault, one per environment, or on Azure the machine's workload identity. Each mesh is listed in Studio and can be revoked on its own. Check it with leafmesh auth status --check. Replace the key with leafmesh auth rotate: the new key takes over at once (or once an admin approves it, if your organisation requires approval), and the old one is revoked. From 5 December 2026 meshes must run 2.4.497 or later, and API keys and tokens are shown only once, when created or rotated. See Installation → How the mesh signs in.

Hardening Knobs

See Installation → Security & Hardening Knobs for the full env-var reference: rate limits, replay skew window, MCP allowlist, knowledge ingest caps, LLM timeout ceiling, cron min-interval, security headers, etc.

Current Limitations

  • Calls to the mesh's API need your organisation's API key in the X-API-Key header (Studio → API Keys); the mesh itself runs without it. Still put a reverse proxy (nginx, Cloudflare Access, etc.) in front before exposing it to the public internet.
  • No role-based access control (RBAC) inside LeafMesh.
  • No external audit log forwarding out of the box (audit events are emitted to the platform's event feed).

Health Checks

The API server exposes health endpoints:

{ "status": "healthy", "components": { "backend": {"status": "connected", "latency_ms": 2}, "scheduler": {"status": "running"} } }

Integrate with load balancer health checks and Kubernetes probes.

Environment Variables

Use environment variables for secrets:

export REDIS_PASSWORD="your_redis_password" export OPENAI_API_KEY="sk-..." export ANTHROPIC_API_KEY="sk-ant-..."

LeafMesh detects available providers by checking for API keys at startup.

Running more than one instance

For any deployment with two or more instances (multiple App Runner / Container Apps instances, or Kubernetes replicas), set:

export LEAFMESH_WORKERS_MODE=1

on every instance, and point them all at the same Redis. This enables exactly-once event delivery, single-runner background jobs (scheduler, listeners), cross-instance session locking, and human-in-the-loop waits that survive an instance restart. Without it, run a single instance — see Scaling for details.

Next Steps


LeafMesh — Production deployment guide

Last updated: 11/10/2026