Configuration API

Configuration API

Complete reference for the LeafMesh configuration schema. From 2.4.481 the agency's configuration lives in its store, not in a file: you edit it in Studio (its YAML view uses the format shown here), every save is a new version on Studio's versions page (with a diff, and make default restores one), and every pod runs the latest. An existing config.yaml is imported once, then no longer read. All configuration is validated at load time.

Top-Level: LeafMeshConfig

name: "my_system" # Default: "default_mesh" version: "1.0.0" # Default: "1.0.0" architecture: "managed_mesh" # Required: always "managed_mesh" environment: "production" # Default: "development" debug: false # Default: false log_level: "INFO" # Default: "INFO" agents: {} # Required: agent definitions manager: {} # Optional: coordination config mesh: {} # Optional: mesh network config entry_points: [] # Optional: external access points data_structures: {} # Optional: custom data types auto_discover: # Optional: auto-discover agent files directory: "./agents" pattern: "*_agent.py" recursive: true observability: {} # Optional: observability config security: {} # Optional: telemetry_redact_pii self_healing: {} # Optional: agent health watch timeouts: {} # Optional: see Runtime Behaviour Blocks scheduler: {} # Optional runtime: {} # Optional limits: {} # Optional connectors: {} # Optional

The store (Redis or Postgres) is not part of this file. From 2.4.482 it is set only in .env; a persistence: or top-level redis: block is no longer read and logs a warning at boot. See Store (.env) below.

AgentConfig

Required Fields

agents: my_agent: name: "my_agent" # Required: unique identifier

LLM Fields

model: "gpt-4o-mini" # Default: "gpt-4o-mini" prompt: "Your instructions" # System prompt (optional) description: "Agent purpose" # Description (optional) temperature: 0.1 # Default: 0.1 max_tokens: 800 # Default: 800 max_completion_tokens: 1000 # For newer models (optional) reasoning: false # Chain-of-thought (default: false)

Agent Type

agent_type: "llm" # "llm" | "human" | "programmatic" | "external"

External Agent Fields

agent_type: "external" framework: "crewai" # "crewai" | "langgraph" | "autogen" | "custom" connector_config: {} # Framework connection config

Yields & Inputs

yields: # Expected output schema category: "string" confidence: "number" is_valid: "boolean" inputs: # Expected inputs (documentation) user_message: "string"

Routing (can_call)

can_call: - agent: "target_agent" condition: "confidence >= 0.8 && category == 'technical'" call_immediately: false # Default: false

Conditions support && and || syntax (converted to and/or internally).

Condition Operators

TypeOperators
Comparison==, !=, >, <, >=, <=
Logicaland/&&, or/`, not`
Arithmetic+, -, *, /, %
Attributecalling_agent_response.field (nested access)
Constantstrue, false, null

Communication

communication_type: "dual" # "dual" | "chain" | "execute" auto_store_response: true # Auto-store responses (default: true) auto_store_yields: true # Auto-store yields (default: true)

Scaling

scaling: # Replaces parallel / max_concurrent / instances (2.4.484) runs: {max: 3} # Jobs at once across all pods (default: no cap) copies: mode: auto # fixed (default) | auto max: 10 # auto's ceiling (default 10, 1-50) work: "items" # Input field holding the list (or claim_tool) handoff: last # last (default) | each

See Agent Configuration → scaling.

Tool Configuration

tools: ["calculator", "web_request"] tool_choice: "auto" # "auto" | "none" | specific tool name max_tool_calls_per_message: 5 # Range: 0-20, default: 5 tool_call_timeout: 30.0 # Range: 0.1-300 seconds allow_parallel_tool_calls: true # Default: true tool_categories: ["math", "web"] # Tool categories to grant

Adaptive Model Selection

optimization_strategy: "performance" # "performance" | "cost" | "speed" | null

Context Parts

Behavioral instructions injected as separate system messages alongside the agent's prompt. Shapes how the agent responds (tone, safety, flow-awareness) independently from what it does.

KeyLabel injectedPurpose
care[EMPATHY & TONE]Warmth and empathy instructions
sentiment_analysis[SENTIMENT ANALYSIS]Tone detection instructions
guardrails[SAFETY GUARDRAILS]Safety rules — what the agent must never do
flows[FLOW INSTRUCTIONS]Per-caller routing behaviour — what to do differently based on who called the agent

Custom keys are also supported and receive an auto-generated label (my_key → [MY KEY]).

context_parts: care: | Always be empathetic. Acknowledge frustration before solving. sentiment_analysis: | Detect emotional tone. Adapt response to user mood. guardrails: | No PII disclosure. No internal system details. No timeline promises. flows: | When called from the entry point (no from_agent): - New user. Greet warmly and gather their primary need. When called from client (human agent): - Human has already responded. Skip re-greeting. Summarise and proceed. When called from scheduler_agent: - Scheduled run. Skip greeting entirely. Produce a structured summary.

All keys are optional — use any combination. See Guardrails for patterns.

Human Agent Fields

agent_type: "human" is_human_powered: true human_interface: "webhook" # "default" (Inbox) | "api" | "webhook" | "custom" human_timeout_seconds: 300 # Default: 300 human_context_template: "..." # Template for human context human_prompt_template: "..." # Template for human prompts fallback_on_timeout: false # Default: false (a timeout escalates, never an assumed answer) fallback_response: {} # Used only when fallback_on_timeout is true webhook_config: # Not needed for an Inbox seat (human_interface: "default") connection: "review-webhook" # Outbound webhook record: address, header/query rows, inbound_token outbound_timeout: 30 # Default: 30 inbound_endpoint: "/webhook/greet_user" response_mapping: {} max_retries: 3 # Default: 3 retry_delay: 5 # Default: 5 seconds operators: {} # Operator ID → recipient

require_human_confirmation, confirmation_seat and human_escalation_triggers were removed in 2.4.382 — approval is routing. One that is set on is refused at load; one that is off or empty is dropped. To have a person approve work, send it to a human agent with a can_call condition:

can_call: - agent: "finance_lead" # a human agent condition: "needs_approval == true"

Scheduling

wake_up: "0 9 * * *" # Cron | interval "5m" | keyword "@daily"

ManagerConfig

manager: enabled: true # Default: true model: "gpt-4o-mini" # LLM model for Manager analysis temperature: 0.1 # Default: 0.1 max_tokens: 4000 # Default: 4000 domain: "generic" # Manager domain specialization analysis_style: "coordination" # Default: "coordination" prompt: | # Optional: evaluation criteria injected into every analysis This mesh handles customer support. Escalate if the same issue loops more than twice. Watch for advisor confidence scores below 0.6. coordination_rules: {} # Custom rules (max_call_depth, agent_rules, reflection_budget (default 2), max_retries, ...) chain_completion_timeout: 1800.0 # Seconds before checking chain (default: 1800) health_check_interval: 60 # Seconds between health checks agent_timeout_threshold: 180 # Seconds before agent timeout can_intervene: true # Allow interventions (default: true) intervention_triggers: # What triggers intervention - "mesh_loop_detected" - "coordination_rule_violation" - "agent_conflict" routing: # Routing authority (learning-based routing) mode: "static" # "static" (default) or "learning" memory_size: 100 # Max routing decisions to track per pair confidence_threshold: 0.7 # Min success rate to keep a route escalation: # Escalation targets targets: - type: "human_agent" # "human_agent" | "webhook" | "channel" agent: "senior_support" entry_point: "escalation_request" - type: "webhook" connection: "escalation-webhook" # Outbound webhook record: address, headers, token method: "POST" payload_template: customer_id: "{{customer_id}}" severity: "critical" - type: "channel" provider: "slack" channel_id: "C0123456789" message_template: "Escalation: {{issue}}" human_input_rules: # Directly under manager:, not under coordination_rules max_concurrent_requests: 3 max_agent_requests: 5 enable_request_queuing: true timeout_rules: max_timeouts_before_escalation: 2 timeout_escalation_enabled: true escalation_notify_managers: true workflow_pause_rules: max_pause_duration_minutes: 30 max_concurrent_paused_workflows: 2 pause_monitoring_enabled: true human_response_rules: approval: requires_manager_review: false auto_escalate: false escalation: requires_manager_review: true auto_escalate: true timeout: requires_manager_review: true auto_escalate: false

The four rule sets human_input_rules, timeout_rules, workflow_pause_rules and human_response_rules live directly under manager:. Do not put them under manager.coordination_rules:; from 2.4.482 a file that still does is moved at load, with a warning. The values above are the defaults.

MeshConfig

mesh: reply_stream: false # Route mesh replies through the per-session # reply stream (default: false, opt-in). # Always on in multi-worker mode regardless. # Amazon Bedrock — route LLM calls through AWS Bedrock bedrock: connection: "bedrock-main" # "AWS Bedrock" record under Infrastructure → Models: region, credentials, any VPC endpoint profile: "prod" # Optional: AWS CLI profile # Google Vertex AI — route LLM calls through Vertex AI vertex: connection: "vertex-main" # "Google Vertex AI" record under Infrastructure → Models: project ID and location # Microsoft Foundry — route LLM calls through Azure AI Foundry foundry: connection: "foundry-main" # "Azure AI Foundry" record under Infrastructure → Models: endpoint and credentials # api_version: "2024-10-21" # Optional: legacy versioned API

From 2.4.481 a cloud model service's address and credentials are entered only in the vault, under Infrastructure → Models; the block names the record with connection:. An endpoint, URL or key written inline is refused at load. The mesh's own cloud sign-in is under Infrastructure → Cloud access ("AWS access", "Google Cloud access", "Azure access").

mesh.call_timeout is gone. The default mesh_call wait is timeouts.mesh_call_default_timeout_s (default 300 seconds); see timeouts. From 2.4.482 an old mesh.call_timeout is moved there at load, with a warning.

Use bedrock/, vertex/, or foundry/ model prefixes on agents to route through these gateways:

agents: via_bedrock: name: "via_bedrock" model: "bedrock/claude-3.5-sonnet" via_vertex: name: "via_vertex" model: "vertex/gemini-2.5-flash" via_foundry: name: "via_foundry" model: "foundry/gpt-4o"

Store (.env)

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

# .env LEAFMESH_STORE=redis REDIS_HOST=localhost REDIS_PORT=6379 REDIS_PASSWORD=your-password
VariableDefault when unsetWhat it sets
LEAFMESH_STOREredisredis or postgres
Redis
REDIS_URLnoneThe whole server in one URL, e.g. redis://user:pw@host:6379/4. rediss:// turns TLS on. The single names below fill in anything it leaves out.
REDIS_HOSTlocalhostServer host
REDIS_PORT6379Server port
REDIS_PASSWORDnoneServer password
REDIS_DB0Database number
REDIS_DEFAULT_TTL3600 (1 hour)Lifetime of general data (yields, mesh communications), seconds
REDIS_SESSION_TTL604800 (7 days)Lifetime of sessions and conversation history, seconds
REDIS_SSLfalseSet true to require TLS
REDIS_SSL_CERT_REQSrequiredCertificate check: required, optional or none
REDIS_SSL_CA_CERTSnonePath to the CA bundle
REDIS_SSL_CERTFILE, REDIS_SSL_KEYFILEnoneClient certificate and key (mutual TLS)
REDIS_SSL_CHECK_HOSTNAMEtrueCheck the server hostname against its certificate
REDIS_CLUSTER_NODESnoneComma-separated host:port list. Setting it turns on Redis Cluster mode.
Postgres
DATABASE_URLnoneThe whole server in one URL, e.g. postgresql://user:pw@host:5432/db?sslmode=require. The single names below fill in anything it leaves out.
POSTGRES_HOSTlocalhostServer host
POSTGRES_PORT5432Server port
POSTGRES_DBleafmeshDatabase name
POSTGRES_USER, POSTGRES_PASSWORDnoneCredentials
POSTGRES_SSLMODEunset (the driver's own default)Postgres SSL mode
POSTGRES_DEFAULT_TTL3600 (1 hour)Lifetime of general data, seconds
POSTGRES_SESSION_TTL604800 (7 days)Lifetime of sessions, seconds
POSTGRES_POOL_MIN1Smallest connection pool size
POSTGRES_POOL_MAX10Largest connection pool size

Set only what you need; the rest keep their defaults. Studio shows under Infrastructure → Datastores whether the store is reachable, its latency and server, the settings in force and which .env names set them; it never shows the address or password. See Persistence.

Repairing the configuration (leafmesh config)

2.4.492+. When a stored configuration stops the mesh from starting, repair it from the command line with the mesh stopped. The start error ends with: Fix it while the mesh is stopped: leafmesh config check shows each problem; leafmesh config rollback returns to the last version that passes; leafmesh config export / import to edit by hand.

leafmesh config check leafmesh config versions leafmesh config rollback [--to N] leafmesh config export [--version N] leafmesh config import <file>
CommandWhat it does
checkLoads the stored configuration with this SDK's checks and lists every problem with its line. Exits 1 when there is one.
versionsLists the kept versions, newest first, each marked passes or refused, and which one is in use.
rollback [--to N]Makes an earlier version current again (default: the newest that passes), saved as a new version. Nothing is deleted.
export [--version N]Prints the configuration as YAML, with no secrets, to edit by hand.
import <file>Checks a YAML file and saves it as the next version. Refused, with its problems, if it does not pass.

The CLI reads the store from .env (the REDIS_* names, or LEAFMESH_STORE=postgres with the POSTGRES_* names), and the agency from --agency <name>, else LEAFMESH_AGENCY_NAME, else the project's configs/config.yaml. The versions are the ones Studio's Versions page lists.

API Server

api: cors_origins: [] # Additional CORS origins

api.cors_origins and api.public_base_url have no fixed default, so a new agency's YAML leaves them out: cors_origins is empty until you list origins, and public_base_url is learned from the first request.

LeafMesh ships with a built-in CORS allowlist — https://platform.leafcraft.ai plus localhost dev ports (3000, 3001, 5173, 5174, 8080). Origins listed under api.cors_origins are appended to that default; you don't need to re-list the built-in entries.

api: cors_origins: - https://my-internal-tool.example.com - https://staging-studio.acme.com

There is no env var override: the YAML key is the single extension point. The API server has no built-in authentication, so the allowlist policy is intentionally narrow — gate broader access via a reverse proxy with auth.

Entry Points

entry_points: - name: "support_request" # Stable external name target: "triage_agent" # Target agent description: "Description" condition: "always" # When to trigger

Runtime Behaviour Blocks

Five optional top-level blocks that tune how the agency behaves at runtime. Introduced in v2.4.131, where these settings moved out of environment variables and became declared config — versioned with your agency, visible in Agent Studio, and editable through the config API.

Every field is optional and every field is independent. Declare only what you want to change; anything you leave out keeps the SDK's default. An empty block is the same as no block. From 2.4.482 a new agency's YAML is written with every one of these settings and its default value, so you can see and edit them in place.

Three settings have no fixed default and are left out on purpose: runtime.lease_heartbeat_s (follows lease_seconds / 3), api.public_base_url (learned from the first request) and api.cors_origins (empty until you list origins).

timeouts: llm_hard_timeout_s: 300 scheduler: misfire_grace_s: 1800 limits: max_parallel_tool_calls: 4

Booleans are three-state. A connector toggle can be absent (use the default), true, or false. Writing false is not the same as leaving it out, and false round-trips through save/reload intact rather than reverting.

timeouts

How long the agency waits before giving up.

FieldDefaultMeaning
llm_hard_timeout_s90Hard ceiling on a single LLM call, seconds. A per-agent llm_hard_timeout_s overrides it.
llm_tool_loop_timeout_multiplier3Tool-loop budget = hard timeout × this.
llm_tool_loop_timeout_cap_s600Absolute cap on the tool loop regardless of the multiplier.
mesh_call_default_timeout_s300Default mesh_call wait when no timeout= is passed.
ack_completion_timeout_s600How long a queued unit of work may run before it is redelivered. Floor 30.
sse_session_ttl_s900SSE session lifetime, seconds. Clamped to 60–3600.
hitl_redrive_grace_s20Grace before a human-in-the-loop request may be redriven. Floor 5.
super_agent_max_dispatch_s14400Hard ceiling on one super-agent dispatch, seconds (4 hours).

scheduler

Cadence and retention for scheduled work.

FieldDefaultMeaning
cron_min_interval_seconds60Floor on wake_up cron cadence. Guards against a runaway schedule.
misfire_grace_s3600How late a missed scheduled run may still fire.
followup_tick_s2How often the follow-up scheduler wakes. Floor 0.5.
followup_max_delay_s2592000Furthest ahead a follow-up may be scheduled (30 days).
followup_record_ttl_s604800How long a follow-up record is retained (7 days). Floor 1 hour.
hitl_reaper_interval_s600How often expired human-in-the-loop requests are swept.
hitl_reaper_grace_s900Grace before an expired HITL request is reaped. Floor 60.

runtime

Connection liveness and coordination between workers. Most deployments never touch these — the defaults suit a healthy local network. Raise the lease and pub/sub windows on a flaky or high-latency link.

FieldDefaultMeaning
pubsub_poll_s5Max seconds one pub/sub read may block.
pubsub_ping_quiet_s30Silence before pinging, to tell quiet from dead.
pubsub_dead_s90Total unanswered silence before the connection is rebuilt.
lease_seconds30Singleton-service lease lifetime. Raise on an unreliable link.
lease_heartbeat_sno fixed default (lease_seconds / 3)Lease renewal interval. Left out of the YAML unless you set it.
dispatch_claim_ttl_s600How long a dispatch claim is held so redelivered work doesn't run twice. Floor 30.
eventbus_mode_guard_ttl_s30Event-bus mode-guard heartbeat TTL. Floor 10.
reclaim_min_idle_ms720000Minimum idle time before stalled work may be reclaimed. Setting this below the ack timeout steals work that is still running.
config_sync_poll_s15How often a worker re-reads config for cross-worker sync.
skills_eagerfalsetrue puts every skill's full text in the prompt; false sends a short index and loads a skill when the agent needs it. An agent's own skills_eager overrides it.
live_model_discoverytrueAsks each provider for its current model list. Set false for offline installs.

limits

Ceilings on size, rate and concurrency.

FieldDefaultMeaning
webhook_max_payload_bytes1048576Largest accepted inbound webhook body (1 MiB).
request_max_payload_bytes4194304Largest request body the agency accepts on its run and config routes (4 MiB); anything bigger is refused before it is read. Files go through the conversation-file upload instead.
webhook_rate_limit_max60Inbound webhooks allowed per window.
webhook_rate_limit_window_s60Webhook rate-limit window.
webhook_replay_skew_s300How old a signed webhook may be before it's rejected as a replay.
max_session_history_bytes5242880Stored conversation history per session (5 MiB).
session_gather_concurrency4Parallel session reads when the API lists sessions.
session_idle_active_s1800A session shows as "active" while it had activity in the last this-many seconds, then "idle". Ended sessions show their end status either way.
max_parallel_tool_calls8Tools executed concurrently within one turn.
tool_result_max_chars100000Truncation cap on a single tool's output.
followup_context_max_kb16Context carried into a scheduled follow-up.
file_max_bytes10485760Largest conversation file the agency keeps (10 MiB): an Inbox upload, or a file an agent hands to a person.
file_ttl_s604800How long a conversation file stays downloadable (7 days).
knowledge_max_ingest_total_bytes52428800Total payload ceiling for one ingest request (50 MiB).
knowledge_query_rate_limit_max120Knowledge/RAG queries allowed per window.
knowledge_query_rate_limit_window_s60Knowledge query rate-limit window.
tool_failure_breaker3Consecutive failures of one tool before its circuit breaker opens.
consumer_inflight_max64Concurrent agent executions across all work queues.

Per-document knowledge caps are per provider, not global — a policy index and a scraped-web index rarely want the same ceiling:

knowledge: providers: policies: settings: max_docs_per_ingest: 1000 # default 1000 max_doc_bytes: 2097152 # default 2 MiB

connectors

Behaviour of outbound calls to external frameworks. All three default to true; set one to false to turn it off.

FieldDefaultMeaning
traceparent_injecttrueInject the W3C traceparent header into outbound connector calls. Set false for strict WAFs that reject unknown headers.
external_usage_stamptrueRecord token-usage attributes reported by external frameworks. Set false to keep third-party cost numbers out of your own totals.
external_trace_capturetrueCapture the external framework's own trace data alongside yours.

security

FieldDefaultMeaning
telemetry_redact_piitrueEach input and output content value in a trace is replaced whole with <redacted bytes:N> (not per-word PII detection); names, models, tokens, cost, status, errors and timings stay visible. On by default since 2.4.480; set false to keep content readable. Credentials are always masked either way.

The prompt guardrail is not a setting: it always runs.

self_healing

Watches agent health and, only when you allow it, restarts a failing agent or starts a backup for it. Strict block: unknown keys are refused.

FieldDefaultMeaning
enabledtrueWatch health, raise healing.* events, send an Inbox notice.
actions_enabledfalseAllow restart and backup actions.
consecutive_failures5Failures in a row before an agent is critical.
error_rate0.3Error share of recent runs before an agent is critical.
latency_factor3.0Slower than this multiple of the agent's own median latency counts as slow.
min_quality_score0.4Reported quality below this is critical.
cooldown_s600Seconds before the same agent may be acted on again.
max_actions_per_hour3Actions per agent per rolling hour.
max_backups_per_agent1Backups that may run for one agent at a time.
monitoring_interval_s5How often health is sampled, seconds.

See Self-Healing Networks.

Editing these at runtime

All five blocks are readable and writable through the config API and editable in Agent Studio:

GET /api/yaml/config # read the current declared config PATCH /api/yaml/config # merge changes in

PATCH merges, so you send only the fields you're changing. To clear a field and return it to its default, send it explicitly as null — omitting it keeps the existing value. Every save is a new version of the agency's configuration in its store, and survives a restart.

From 2.4.484 a saved change applies without a restart, on every pod, and reaches the other pods within about 15 seconds. The Manager and its summarizer take their settings live (rules, timing, routing, model, what it listens to). A change that still needs a reload makes the agency reload itself in place within seconds: brokers, self_healing.enabled, api.cors_origins, lease timing, architecture, auto_discover, limits.consumer_inflight_max, and switching the Manager on or off; a human seat's channels count as reload too. Only evolution_api's host, port and enabled need a process restart.

From 2.4.485 every row of Studio's schema (GET /api/schema/mesh and GET /api/schema/agent) has applies: live, reload or process_restart. restart_required is true only when applies is process_restart.

Complete Example

name: "support_system" version: "1.0.0" architecture: "managed_mesh" environment: "production" agents: triage: name: "triage" model: "gpt-4o-mini" temperature: 0.1 max_tokens: 800 prompt: "Classify requests by urgency and category." yields: urgency: "number" category: "string" can_call: - agent: "specialist" condition: "urgency >= 7" specialist: name: "specialist" model: "gpt-4o" tools: ["web_request", "calculator"] max_tool_calls_per_message: 5 prompt: "Provide detailed analysis." yields: analysis: "string" confidence: "number" manager: enabled: true model: "gpt-4o-mini" coordination_rules: max_agent_calls: 10 mesh: max_call_depth: 5 loop_detection: true entry_points: - name: "support" target: "triage"

With the store in .env:

# .env LEAFMESH_STORE=redis REDIS_HOST=localhost REDIS_PORT=6379

Next Steps


LeafMesh — Configuration API reference

Last updated: 11/10/2026