create-leafmesh 2.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- create_leafmesh/__init__.py +3 -0
- create_leafmesh/cli.py +252 -0
- create_leafmesh/create.py +106 -0
- create_leafmesh/templates/Dockerfile +21 -0
- create_leafmesh/templates/README.md +309 -0
- create_leafmesh/templates/agency/__init__.py +0 -0
- create_leafmesh/templates/agency/advisor_agent.py +151 -0
- create_leafmesh/templates/agency/external_agents.py +278 -0
- create_leafmesh/templates/agency/fallback_researcher_agent.py +80 -0
- create_leafmesh/templates/agency/greeter_agent.py +79 -0
- create_leafmesh/templates/agency/processor_agent.py +90 -0
- create_leafmesh/templates/agency/researcher_agent.py +99 -0
- create_leafmesh/templates/agency/scheduler_agent.py +67 -0
- create_leafmesh/templates/agency/tools.py +123 -0
- create_leafmesh/templates/claude_skills/leafmesh/SKILL.md +2049 -0
- create_leafmesh/templates/claude_skills/leafmesh/agent-config-fields.md +1309 -0
- create_leafmesh/templates/claude_skills/leafmesh/examples.md +537 -0
- create_leafmesh/templates/claude_skills/leafmesh/reference.md +492 -0
- create_leafmesh/templates/configs/config.yaml +1028 -0
- create_leafmesh/templates/docker-compose.yml +28 -0
- create_leafmesh/templates/dockerignore +17 -0
- create_leafmesh/templates/env +109 -0
- create_leafmesh/templates/gitignore +33 -0
- create_leafmesh/templates/hitl_stub_receiver.py +149 -0
- create_leafmesh/templates/main.py +105 -0
- create_leafmesh/templates/requirements.txt +10 -0
- create_leafmesh-2.1.0.dist-info/METADATA +6 -0
- create_leafmesh-2.1.0.dist-info/RECORD +31 -0
- create_leafmesh-2.1.0.dist-info/WHEEL +5 -0
- create_leafmesh-2.1.0.dist-info/entry_points.txt +2 -0
- create_leafmesh-2.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1028 @@
|
|
|
1
|
+
name: "{{project_name}}"
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
architecture: "managed_mesh"
|
|
4
|
+
environment: "development" # "development" or "production"
|
|
5
|
+
debug: true
|
|
6
|
+
log_level: "INFO"
|
|
7
|
+
|
|
8
|
+
redis:
|
|
9
|
+
host: "${REDIS_HOST:localhost}"
|
|
10
|
+
port: ${REDIS_PORT:6379}
|
|
11
|
+
db: 0
|
|
12
|
+
password: "${REDIS_PASSWORD:}"
|
|
13
|
+
auto_storage: true
|
|
14
|
+
decode_responses: true # Decode Redis byte responses to strings
|
|
15
|
+
default_ttl: 3600 # Default key TTL in seconds
|
|
16
|
+
session_ttl: 7200 # Session TTL in seconds
|
|
17
|
+
# cluster_mode: true # Enable Redis cluster mode
|
|
18
|
+
# cluster_nodes: # Cluster node addresses
|
|
19
|
+
# - "redis-node1:6379"
|
|
20
|
+
# - "redis-node2:6379"
|
|
21
|
+
# - "redis-node3:6379"
|
|
22
|
+
|
|
23
|
+
# TLS / encryption-in-transit
|
|
24
|
+
# Enable when your Redis server requires TLS (rediss://).
|
|
25
|
+
# ssl: true
|
|
26
|
+
# ssl_cert_reqs: required # required | optional | none
|
|
27
|
+
# ssl_ca_certs: /etc/ssl/certs/redis-ca.crt
|
|
28
|
+
# ssl_certfile: /etc/ssl/certs/redis-client.crt # mTLS, optional
|
|
29
|
+
# ssl_keyfile: /etc/ssl/private/redis-client.key # mTLS, optional
|
|
30
|
+
# ssl_check_hostname: true
|
|
31
|
+
|
|
32
|
+
# ═══════════════════════════════════════════════════
|
|
33
|
+
# API — HTTP server (CORS, etc.)
|
|
34
|
+
# ═══════════════════════════════════════════════════
|
|
35
|
+
# The SDK ships with a built-in CORS allowlist:
|
|
36
|
+
# - https://platform.leafcraft.ai (hosted Studio)
|
|
37
|
+
# - http://localhost:3000 / 3001 / 5173 / 5174 / 8080 (common dev ports)
|
|
38
|
+
# Add additional origins below if you serve your own UI from a different host.
|
|
39
|
+
# api:
|
|
40
|
+
# cors_origins:
|
|
41
|
+
# - https://my-internal-tool.example.com
|
|
42
|
+
# - https://my-staging-studio.acme.com
|
|
43
|
+
|
|
44
|
+
# Auto-discover agent files in agency/ directory
|
|
45
|
+
# SDK matches Python function names to YAML agent names
|
|
46
|
+
auto_discover:
|
|
47
|
+
directory: "./agency"
|
|
48
|
+
pattern: "*_agent.py"
|
|
49
|
+
# recursive: true # Search subdirectories (default: true)
|
|
50
|
+
|
|
51
|
+
# ═══════════════════════════════════════════════════
|
|
52
|
+
# MANAGER — Built-in mesh coordinator + conversation analyzer
|
|
53
|
+
#
|
|
54
|
+
# Two built-in agents, ONE config section:
|
|
55
|
+
# Summarizer — LLM-powered, analyzes every agent event automatically
|
|
56
|
+
# Manager — Pure logic, enforces rules, retries, halts, escalates
|
|
57
|
+
#
|
|
58
|
+
# The "model" and "domain" fields drive the Summarizer's LLM calls.
|
|
59
|
+
# The Manager never calls an LLM — it acts on the Summarizer's analysis.
|
|
60
|
+
# ═══════════════════════════════════════════════════
|
|
61
|
+
manager:
|
|
62
|
+
enabled: true
|
|
63
|
+
model: "gpt-4o-mini" # Used by Summarizer for LLM analysis
|
|
64
|
+
domain: "generic" # Summarizer domain: "generic" | "ecommerce" | "data_analysis"
|
|
65
|
+
# ── Learning-based routing (BRD-008) ──
|
|
66
|
+
# Routes mesh_call requests to agents based on past success patterns.
|
|
67
|
+
# "learning" mode accumulates routing decisions in Redis and improves over time.
|
|
68
|
+
# No external dependencies — works with Redis only.
|
|
69
|
+
routing:
|
|
70
|
+
mode: "learning" # "static" (YAML rules only) or "learning" (adaptive)
|
|
71
|
+
memory_size: 100 # Max routing decisions to remember
|
|
72
|
+
confidence_threshold: 0.7 # Min confidence to accept a learned route
|
|
73
|
+
fallback: "all" # Fallback when confidence too low: "all" evaluates every can_call
|
|
74
|
+
decay_days: 30 # Days before old routing memory decays
|
|
75
|
+
|
|
76
|
+
# ── Escalation targets (BRD-011) ──
|
|
77
|
+
# When the manager detects repeated failures or timeouts, it escalates.
|
|
78
|
+
# Human agent escalation works out of the box. Webhook/channel need credentials.
|
|
79
|
+
escalation:
|
|
80
|
+
targets:
|
|
81
|
+
# Human agent escalation — routes to the client human agent
|
|
82
|
+
- type: "human_agent"
|
|
83
|
+
agent: "client"
|
|
84
|
+
# entry_point: "human_contact" # Optional: specific entry point
|
|
85
|
+
|
|
86
|
+
# Webhook escalation (uncomment + configure URL)
|
|
87
|
+
# - type: "webhook"
|
|
88
|
+
# url: "${ESCALATION_WEBHOOK_URL:}"
|
|
89
|
+
# method: "POST"
|
|
90
|
+
# headers:
|
|
91
|
+
# Authorization: "Bearer ${ESCALATION_WEBHOOK_TOKEN:}"
|
|
92
|
+
# Content-Type: "application/json"
|
|
93
|
+
# payload_template:
|
|
94
|
+
# incident: "{{incident_id}}"
|
|
95
|
+
# severity: "{{severity}}"
|
|
96
|
+
# message: "{{message}}"
|
|
97
|
+
|
|
98
|
+
# Channel escalation (uncomment + configure provider)
|
|
99
|
+
# - type: "channel"
|
|
100
|
+
# provider: "slack" # slack | telegram | discord | whatsapp | teams
|
|
101
|
+
# channel_id: "${ESCALATION_SLACK_CHANNEL:}"
|
|
102
|
+
# message_template: "🚨 Escalation: {{message}} (session: {{session_id}})"
|
|
103
|
+
|
|
104
|
+
auto_escalate:
|
|
105
|
+
max_retries: 3 # Max retry attempts before escalating
|
|
106
|
+
max_errors_per_session: 5 # Error count threshold per session
|
|
107
|
+
timeout_threshold: 2 # Consecutive timeouts before escalating
|
|
108
|
+
|
|
109
|
+
# can_intervene: true # Allow manager interventions (default: true)
|
|
110
|
+
# # Set false for read-only monitoring mode
|
|
111
|
+
|
|
112
|
+
# ── Everything below has sensible defaults — uncomment only to override ──
|
|
113
|
+
# coordination_rules:
|
|
114
|
+
# score_threshold: 0.7
|
|
115
|
+
# max_retries: 3
|
|
116
|
+
# agent_rules:
|
|
117
|
+
# processor_agent:
|
|
118
|
+
# min_items: 1
|
|
119
|
+
# max_items: 100
|
|
120
|
+
# health_check_interval: 60 # Seconds between health checks (default: 60)
|
|
121
|
+
# agent_timeout_threshold: 180 # Seconds before agent considered timed out (default: 180)
|
|
122
|
+
# chain_completion_timeout: 60 # Seconds to wait for can_call chain (default: 60)
|
|
123
|
+
|
|
124
|
+
# Mesh settings — call timeout + cloud LLM provider configs
|
|
125
|
+
mesh:
|
|
126
|
+
call_timeout: 60
|
|
127
|
+
|
|
128
|
+
# ── Cloud LLM Providers (uncomment to use) ──
|
|
129
|
+
# bedrock:
|
|
130
|
+
# region: "us-east-1" # AWS region
|
|
131
|
+
# # profile: "default" # AWS profile from ~/.aws/credentials
|
|
132
|
+
# # endpoint_url: "" # Custom Bedrock endpoint (optional)
|
|
133
|
+
# # Auth: AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY env vars, or IAM role
|
|
134
|
+
#
|
|
135
|
+
# vertex:
|
|
136
|
+
# project: "my-gcp-project" # GCP project ID (required)
|
|
137
|
+
# location: "us-central1" # GCP region
|
|
138
|
+
# # Auth: GOOGLE_APPLICATION_CREDENTIALS or gcloud auth
|
|
139
|
+
#
|
|
140
|
+
# foundry:
|
|
141
|
+
# endpoint: "https://my-resource.openai.azure.com" # Azure AI Foundry endpoint (required)
|
|
142
|
+
# # api_version: "2024-10-21" # Omit for v1 mode (recommended), set for legacy Azure mode
|
|
143
|
+
# # Auth: AZURE_FOUNDRY_API_KEY or AZURE_FOUNDRY_TOKEN env vars
|
|
144
|
+
#
|
|
145
|
+
# ── Local model server (vLLM, SGLang, Ollama, llama.cpp, etc.) ──
|
|
146
|
+
# Most servers expose OpenAI-compatible /v1/chat/completions — use server_type: openai
|
|
147
|
+
# local:
|
|
148
|
+
# endpoint: "http://localhost:8000/v1/chat/completions" # vLLM/SGLang default
|
|
149
|
+
# server_type: "openai" # "openai" | "ollama" | "textgen" | "huggingface" (auto-detected if omitted)
|
|
150
|
+
# timeout: 120 # Seconds (local models can be slow on CPU)
|
|
151
|
+
# # headers:
|
|
152
|
+
# # Authorization: "Bearer ${VLLM_API_KEY:}"
|
|
153
|
+
|
|
154
|
+
# ═══════════════════════════════════════════════════
|
|
155
|
+
# ENTRY POINTS — Named portals into the mesh
|
|
156
|
+
# Use: await leafmesh.mesh_call("entry_point_name", data)
|
|
157
|
+
# This is the ONLY way to trigger agent workflows externally
|
|
158
|
+
# ═══════════════════════════════════════════════════
|
|
159
|
+
entry_points:
|
|
160
|
+
- name: "greet_user"
|
|
161
|
+
target: "greeter_agent"
|
|
162
|
+
description: "Main entry — greets user and starts the agent chain"
|
|
163
|
+
# condition: "always" # Optional trigger condition
|
|
164
|
+
|
|
165
|
+
- name: "human_contact"
|
|
166
|
+
target: "client"
|
|
167
|
+
description: "Human-initiated — client contacts the mesh via channel/webhook"
|
|
168
|
+
|
|
169
|
+
- name: "process_data"
|
|
170
|
+
target: "processor_agent"
|
|
171
|
+
description: "Direct data processing bypass"
|
|
172
|
+
|
|
173
|
+
- name: "research"
|
|
174
|
+
target: "researcher_agent"
|
|
175
|
+
description: "Direct research — bypasses greeting flow"
|
|
176
|
+
|
|
177
|
+
- name: "advise"
|
|
178
|
+
target: "advisor_agent"
|
|
179
|
+
description: "Direct advice request — ad-hoc recommendations"
|
|
180
|
+
|
|
181
|
+
- name: "scheduled_report"
|
|
182
|
+
target: "scheduler_agent"
|
|
183
|
+
description: "On-demand status report (also runs on cron schedule)"
|
|
184
|
+
|
|
185
|
+
# ═══════════════════════════════════════════════════
|
|
186
|
+
# AGENTS — 4 types: human, llm, programmatic, external
|
|
187
|
+
#
|
|
188
|
+
# Registration:
|
|
189
|
+
# - agency/*_agent.py → auto_discover matches function names to YAML names
|
|
190
|
+
# - Standalone decorators: @chain, @compose, @pre_compose (no leafmesh instance needed)
|
|
191
|
+
#
|
|
192
|
+
# Data flow — HITL (Human-in-the-Loop):
|
|
193
|
+
#
|
|
194
|
+
# Scenario 1 (system-initiated):
|
|
195
|
+
# mesh_call("greet_user", data) → greeter_agent → client (HITL)
|
|
196
|
+
# → [human reviews in ADK-Frontend inbox] → processor_agent
|
|
197
|
+
# → researcher_agent + fallback_researcher_agent
|
|
198
|
+
# → advisor_agent (OR fan-in)
|
|
199
|
+
#
|
|
200
|
+
# Scenario 2 (human-initiated):
|
|
201
|
+
# webhook to "human_contact" → client → greeter_agent → client (HITL)
|
|
202
|
+
# → [human reviews in ADK-Frontend inbox] → processor_agent
|
|
203
|
+
# → researcher_agent + fallback_researcher_agent
|
|
204
|
+
# → advisor_agent (OR fan-in)
|
|
205
|
+
#
|
|
206
|
+
# Direct entries:
|
|
207
|
+
# mesh_call("research", data) → researcher_agent (standalone)
|
|
208
|
+
# mesh_call("advise", data) → advisor_agent (standalone)
|
|
209
|
+
#
|
|
210
|
+
# Scheduled + on-demand:
|
|
211
|
+
# cron "0 9 * * *" → scheduler_agent → advisor_agent (daily report analysis)
|
|
212
|
+
# mesh_call("scheduled_report", data) → scheduler_agent → advisor_agent
|
|
213
|
+
# ═══════════════════════════════════════════════════
|
|
214
|
+
agents:
|
|
215
|
+
|
|
216
|
+
# ─────────────────────────────────────────────
|
|
217
|
+
# HUMAN AGENT — Receives input via ADK-Frontend inbox
|
|
218
|
+
# No Python file needed. The mesh handles everything.
|
|
219
|
+
#
|
|
220
|
+
# human_interface options:
|
|
221
|
+
# "default" — ADK-Frontend HITL inbox (recommended)
|
|
222
|
+
# Writes request to Redis, emits stream event.
|
|
223
|
+
# Human replies via the ADK-Frontend UI.
|
|
224
|
+
# Supports parallel requests per session.
|
|
225
|
+
# "webhook" — External webhook (self-hosted)
|
|
226
|
+
# POSTs to outbound_url, human responds via inbound webhook.
|
|
227
|
+
# Also supports native channel adapters (Slack, Telegram, etc.)
|
|
228
|
+
# "api" — Python callback handler (testing/custom integrations)
|
|
229
|
+
#
|
|
230
|
+
# HITL (Human-in-the-Loop) dual-mode flow:
|
|
231
|
+
# 1. System-initiated: greeter → client (HITL) → processor
|
|
232
|
+
# - Greeter sends result to client for human review
|
|
233
|
+
# - Human sees request in ADK-Frontend inbox
|
|
234
|
+
# - Human responds → routes to processor
|
|
235
|
+
#
|
|
236
|
+
# 2. Human-initiated: client → greeter → client (HITL) → processor
|
|
237
|
+
# - Human contacts mesh via webhook to "human_contact" entry point
|
|
238
|
+
# - Client routes to greeter (from_agent not set → first can_call match)
|
|
239
|
+
# - Greeter responds back to client (dual callback)
|
|
240
|
+
# - Human reviews in inbox → responds → routes to processor
|
|
241
|
+
#
|
|
242
|
+
# The can_call conditions use "from_agent" to distinguish who called:
|
|
243
|
+
# - No from_agent → first contact, route to greeter
|
|
244
|
+
# - from_agent == "greeter_agent" → greeter finished, route to processor
|
|
245
|
+
# ─────────────────────────────────────────────
|
|
246
|
+
client:
|
|
247
|
+
name: "client"
|
|
248
|
+
agent_type: "human"
|
|
249
|
+
is_human_powered: true
|
|
250
|
+
human_interface: "default" # ADK-Frontend inbox (recommended)
|
|
251
|
+
communication_type: "dual" # dual mode: request + wait for human response
|
|
252
|
+
human_timeout_seconds: 300
|
|
253
|
+
# operator_ids: # Operators who can see this agent's inbox requests
|
|
254
|
+
# - "alice@company.com" # Leave empty (or omit) for broadcast — all operators see it
|
|
255
|
+
# - "bob@company.com"
|
|
256
|
+
|
|
257
|
+
# Human-specific templates (customize how context/prompts are presented)
|
|
258
|
+
# human_context_template: "Session {{session_id}}: {{context}}"
|
|
259
|
+
# human_prompt_template: "Please review the following and respond: {{message}}"
|
|
260
|
+
|
|
261
|
+
# Require explicit human confirmation before proceeding
|
|
262
|
+
# require_human_confirmation: false
|
|
263
|
+
|
|
264
|
+
# Conditions that trigger human escalation (e.g. keywords in the request)
|
|
265
|
+
# human_escalation_triggers:
|
|
266
|
+
# - "urgent"
|
|
267
|
+
# - "high_value"
|
|
268
|
+
|
|
269
|
+
# Fallback when human doesn't respond in time
|
|
270
|
+
# fallback_on_timeout: true
|
|
271
|
+
# fallback_response:
|
|
272
|
+
# decision: "timeout_default"
|
|
273
|
+
# message: "Request timed out"
|
|
274
|
+
|
|
275
|
+
# ── Webhook config (only needed when human_interface: "webhook") ──
|
|
276
|
+
# For self-hosted deployments without ADK-Frontend.
|
|
277
|
+
# Outbound notifies external system, inbound receives human response.
|
|
278
|
+
# NOTE: inbound_endpoint is auto-derived from entry_points — no need to set it.
|
|
279
|
+
# webhook_config:
|
|
280
|
+
# outbound_url: "http://127.0.0.1:9999/human-notify"
|
|
281
|
+
# outbound_headers:
|
|
282
|
+
# Content-Type: "application/json"
|
|
283
|
+
# # Authorization: "Bearer ${WEBHOOK_TOKEN:}"
|
|
284
|
+
# outbound_timeout: 30
|
|
285
|
+
# # inbound_auth_token: "${WEBHOOK_AUTH_TOKEN:}"
|
|
286
|
+
# max_retries: 1
|
|
287
|
+
# retry_delay: 2
|
|
288
|
+
# # response_mapping:
|
|
289
|
+
# # user_reply: "response"
|
|
290
|
+
|
|
291
|
+
# ── Native channel adapters (only needed when human_interface: "webhook") ──
|
|
292
|
+
# Connect this human agent directly to messaging platforms.
|
|
293
|
+
# The SDK registers inbound webhook routes automatically on startup.
|
|
294
|
+
# Uncomment + add credentials for the channels you want.
|
|
295
|
+
#
|
|
296
|
+
# Inbound routes registered per channel:
|
|
297
|
+
# Slack: POST /channels/slack/client/events
|
|
298
|
+
# Telegram: POST /channels/telegram/client/webhook
|
|
299
|
+
# Discord: POST /channels/discord/client/interactions
|
|
300
|
+
# WhatsApp: GET /channels/whatsapp/client/webhook (verification)
|
|
301
|
+
# POST /channels/whatsapp/client/webhook (messages)
|
|
302
|
+
# Teams: POST /channels/teams/client/messages
|
|
303
|
+
# channels:
|
|
304
|
+
# slack:
|
|
305
|
+
# bot_token: "${SLACK_BOT_TOKEN:}" # xoxb-… Bot OAuth token
|
|
306
|
+
# signing_secret: "${SLACK_SIGNING_SECRET:}" # HMAC-SHA256 signing secret
|
|
307
|
+
# listen_channels: ["${SLACK_CHANNEL_ID:}"] # Channel IDs (empty = all)
|
|
308
|
+
# post_channel: "${SLACK_CHANNEL_ID:}"
|
|
309
|
+
#
|
|
310
|
+
# telegram:
|
|
311
|
+
# bot_token: "${TELEGRAM_BOT_TOKEN:}" # Token from @BotFather
|
|
312
|
+
# signing_secret: "${TELEGRAM_SECRET_TOKEN:}" # Optional webhook secret
|
|
313
|
+
# listen_channels: [] # Chat IDs (empty = all)
|
|
314
|
+
# post_channel: ""
|
|
315
|
+
#
|
|
316
|
+
# discord:
|
|
317
|
+
# bot_token: "${DISCORD_BOT_TOKEN:}" # Bot token (no "Bot " prefix)
|
|
318
|
+
# signing_secret: "${DISCORD_PUBLIC_KEY:}" # App public key (Ed25519)
|
|
319
|
+
# listen_channels: [] # Channel IDs (empty = all)
|
|
320
|
+
# post_channel: ""
|
|
321
|
+
#
|
|
322
|
+
# whatsapp:
|
|
323
|
+
# bot_token: "${WHATSAPP_ACCESS_TOKEN:}" # Meta Graph API access token
|
|
324
|
+
# signing_secret: "${META_APP_SECRET:}" # Meta app secret (HMAC-SHA256)
|
|
325
|
+
# post_channel: "${WHATSAPP_PHONE_NUMBER_ID:}" # Phone number ID (not phone number)
|
|
326
|
+
# verify_token: "leafmesh_whatsapp_verify" # Match this in Meta developer dashboard
|
|
327
|
+
#
|
|
328
|
+
# teams:
|
|
329
|
+
# bot_token: "${TEAMS_APP_ID:}" # Bot Framework App ID
|
|
330
|
+
# signing_secret: "${TEAMS_APP_PASSWORD:}" # Bot Framework App password
|
|
331
|
+
# post_channel: "" # Set at runtime from inbound activity
|
|
332
|
+
|
|
333
|
+
yields:
|
|
334
|
+
request_data: "object"
|
|
335
|
+
|
|
336
|
+
inputs:
|
|
337
|
+
user_message: "string"
|
|
338
|
+
request_type: "string"
|
|
339
|
+
|
|
340
|
+
# auto_store_response: true # Auto-store responses in Redis (default: true)
|
|
341
|
+
# auto_store_yields: true # Auto-store yields in Redis (default: true)
|
|
342
|
+
|
|
343
|
+
# HITL routing — from_agent distinguishes who called the human agent
|
|
344
|
+
# When greeter calls client: from_agent == "greeter_agent" → route to processor
|
|
345
|
+
# When human initiates (no from_agent): route to greeter first
|
|
346
|
+
can_call:
|
|
347
|
+
- agent: "greeter_agent"
|
|
348
|
+
condition: "not calling_agent_response.from_agent"
|
|
349
|
+
- agent: "processor_agent"
|
|
350
|
+
condition: "calling_agent_response.from_agent == 'greeter_agent'"
|
|
351
|
+
|
|
352
|
+
# ─────────────────────────────────────────────
|
|
353
|
+
# LLM AGENT — @pre_compose prepares data, context_parts shape tone
|
|
354
|
+
# auto_discover matches greeter_agent() in agency/greeter_agent.py
|
|
355
|
+
#
|
|
356
|
+
# Flow: processors run → context_parts injected → LLM called →
|
|
357
|
+
# agent function post-processes → can_call chains to next
|
|
358
|
+
# ─────────────────────────────────────────────
|
|
359
|
+
greeter_agent:
|
|
360
|
+
name: "greeter_agent"
|
|
361
|
+
agent_type: "llm"
|
|
362
|
+
description: "Greets the user and gathers their requirements"
|
|
363
|
+
# ── Supported models (auto-routed to correct provider by model name) ──
|
|
364
|
+
# OpenAI: gpt-4o-mini, gpt-4o, gpt-4.1, gpt-4.1-mini, gpt-4.1-nano, gpt-5.1, gpt-5.2
|
|
365
|
+
# OpenAI o: o1, o1-mini, o3, o3-mini, o4-mini (reasoning models — use thinking: true)
|
|
366
|
+
# Anthropic: claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5-20251001
|
|
367
|
+
# Google: gemini-2.0-flash, gemini-2.5-pro, gemini-3-pro-preview
|
|
368
|
+
# DeepSeek: deepseek-chat, deepseek-reasoner (R1 — native chain-of-thought)
|
|
369
|
+
# Bedrock: bedrock/<model-id> (requires mesh.bedrock config)
|
|
370
|
+
# Vertex: vertex/<model-id> (requires mesh.vertex config)
|
|
371
|
+
# Foundry: foundry/<deployment> (requires mesh.foundry config)
|
|
372
|
+
# Local: any name (e.g. llama3, mistral-7b) — requires mesh.local config
|
|
373
|
+
model: "gpt-4o-mini"
|
|
374
|
+
temperature: 0.7
|
|
375
|
+
max_tokens: 1000
|
|
376
|
+
# max_completion_tokens: 2000 # For newer models (o1, gpt-5.x) — use instead of max_tokens
|
|
377
|
+
communication_type: "dual" # Options: "dual", "chain", "execute"
|
|
378
|
+
reasoning: true # SDK chain-of-thought tool injection (works with any model)
|
|
379
|
+
# thinking: true # Native model thinking (Anthropic/OpenAI o-series/Gemini 2.5+)
|
|
380
|
+
# thinking_budget: 8192 # Max thinking tokens (1024-32768)
|
|
381
|
+
# enable_prompt_caching: true # Provider-native prompt caching (Anthropic: ~90% savings)
|
|
382
|
+
# optimization_strategy: "performance" # "performance" | "cost" | "speed"
|
|
383
|
+
|
|
384
|
+
prompt: |
|
|
385
|
+
You are a friendly assistant. Given the user's message,
|
|
386
|
+
greet them warmly and summarize what they need help with.
|
|
387
|
+
Return a clear, structured JSON summary with keys:
|
|
388
|
+
"greeting", "user_need", "suggested_actions"
|
|
389
|
+
|
|
390
|
+
# Structured output — force LLM to respond with valid JSON matching this schema
|
|
391
|
+
# response_format:
|
|
392
|
+
# type: "object"
|
|
393
|
+
# properties:
|
|
394
|
+
# greeting: { type: "string" }
|
|
395
|
+
# user_need: { type: "string" }
|
|
396
|
+
# suggested_actions: { type: "array", items: { type: "string" } }
|
|
397
|
+
# required: ["greeting", "user_need"]
|
|
398
|
+
|
|
399
|
+
# Context parts — injected as separate system messages before LLM call
|
|
400
|
+
# Each part shapes HOW the LLM responds (tone, analysis, safety)
|
|
401
|
+
context_parts:
|
|
402
|
+
care: |
|
|
403
|
+
Always respond with empathy and warmth. Acknowledge the user's
|
|
404
|
+
situation before jumping to solutions. Use encouraging language
|
|
405
|
+
and offer reassurance when the user seems frustrated.
|
|
406
|
+
sentiment_analysis: |
|
|
407
|
+
Analyze the user's emotional tone before responding.
|
|
408
|
+
If negative sentiment detected, prioritize acknowledgment over action.
|
|
409
|
+
If positive, match their energy and build on momentum.
|
|
410
|
+
Include a 'detected_sentiment' field in your JSON response.
|
|
411
|
+
guardrails: |
|
|
412
|
+
Never share internal system details or agent architecture.
|
|
413
|
+
Do not make promises about timelines or guarantees.
|
|
414
|
+
If the request is outside your domain, clearly redirect.
|
|
415
|
+
Refuse harmful, illegal, or unethical requests.
|
|
416
|
+
|
|
417
|
+
yields:
|
|
418
|
+
greeting: "string"
|
|
419
|
+
user_input: "string"
|
|
420
|
+
detected_sentiment: "string"
|
|
421
|
+
status: "string"
|
|
422
|
+
|
|
423
|
+
inputs:
|
|
424
|
+
message: "string"
|
|
425
|
+
|
|
426
|
+
# LLM can call these tools during generation
|
|
427
|
+
tools: ["word_count", "timestamp"]
|
|
428
|
+
# tool_categories: ["data"] # Grant access to an entire tool category
|
|
429
|
+
tool_choice: "auto"
|
|
430
|
+
max_tool_calls_per_message: 5
|
|
431
|
+
# tool_call_timeout: 30 # Tool execution timeout in seconds (0.1-300, default: 30)
|
|
432
|
+
# allow_parallel_tool_calls: true # Allow tools to run in parallel (default: true)
|
|
433
|
+
|
|
434
|
+
# memory: true # Simple bool — enable with defaults
|
|
435
|
+
# memory: # Dict form — full control
|
|
436
|
+
# strategy: "recency" # "recency" | "relevance" | "hybrid"
|
|
437
|
+
# limit: 10
|
|
438
|
+
# cross_session: false
|
|
439
|
+
# memory_limit: 10 # Legacy: max feed posts (prefer memory.limit)
|
|
440
|
+
|
|
441
|
+
# auto_store_response: true
|
|
442
|
+
# auto_store_yields: true
|
|
443
|
+
|
|
444
|
+
# Mesh chain — routes to human agent for review before processing
|
|
445
|
+
# In HITL flow: greeter → client (human reviews) → processor
|
|
446
|
+
can_call:
|
|
447
|
+
- agent: "client"
|
|
448
|
+
|
|
449
|
+
# Narration — plain-English routing hints for the Manager.
|
|
450
|
+
# Evaluated by the Summarizer when conditions alone don't cover everything.
|
|
451
|
+
# The Manager can route to ANY registered agent, not just those in can_call.
|
|
452
|
+
narration: >
|
|
453
|
+
If the user's request is urgent or mentions an escalation keyword,
|
|
454
|
+
route directly to advisor_agent — skip the processing step.
|
|
455
|
+
If the user asks for a scheduled report, route to scheduler_agent.
|
|
456
|
+
|
|
457
|
+
# ─────────────────────────────────────────────
|
|
458
|
+
# PROGRAMMATIC AGENT — @conditional_chain for branching logic
|
|
459
|
+
# auto_discover matches processor_agent() in agency/processor_agent.py
|
|
460
|
+
#
|
|
461
|
+
# Flow: receives greeter output → processes → conditional_chain
|
|
462
|
+
# branches → can_call with conditions fans out to both agents
|
|
463
|
+
# ─────────────────────────────────────────────
|
|
464
|
+
processor_agent:
|
|
465
|
+
name: "processor_agent"
|
|
466
|
+
agent_type: "programmatic"
|
|
467
|
+
description: "Processes the greeter's output into actionable items"
|
|
468
|
+
communication_type: "chain"
|
|
469
|
+
parallel: true # Enable parallel processing
|
|
470
|
+
max_concurrent: 3 # Max concurrent invocations
|
|
471
|
+
# auto_store_response: true # Auto-store responses in Redis (default: true)
|
|
472
|
+
# auto_store_yields: true # Auto-store yields in Redis (default: true)
|
|
473
|
+
|
|
474
|
+
yields:
|
|
475
|
+
processed_items: "list"
|
|
476
|
+
item_count: "number"
|
|
477
|
+
status: "string"
|
|
478
|
+
alert: "string"
|
|
479
|
+
|
|
480
|
+
inputs:
|
|
481
|
+
greeter_result: "object"
|
|
482
|
+
|
|
483
|
+
# Fan-out: researcher, fallback_researcher, and advisor are all called
|
|
484
|
+
can_call:
|
|
485
|
+
- agent: "researcher_agent"
|
|
486
|
+
condition: "calling_agent_response.item_count > 0"
|
|
487
|
+
- agent: "fallback_researcher_agent"
|
|
488
|
+
condition: "calling_agent_response.item_count > 0"
|
|
489
|
+
- agent: "advisor_agent"
|
|
490
|
+
condition: "calling_agent_response.item_count > 0"
|
|
491
|
+
|
|
492
|
+
# Narration — non-definitive routing the Manager evaluates via the Summarizer.
|
|
493
|
+
# These hints catch cases conditions can't express as boolean checks.
|
|
494
|
+
narration: >
|
|
495
|
+
If the processed items contain anything safety-related or flagged as high-risk,
|
|
496
|
+
route to advisor_agent immediately without waiting for research.
|
|
497
|
+
If the alert field mentions a data quality issue, route to fallback_researcher_agent only.
|
|
498
|
+
|
|
499
|
+
# ─────────────────────────────────────────────
|
|
500
|
+
# LLM AGENT — @chain_with_results for accumulating pipeline
|
|
501
|
+
# auto_discover matches researcher_agent() in agency/researcher_agent.py
|
|
502
|
+
#
|
|
503
|
+
# Features: memory, tool_categories, reasoning, parallel tool calls
|
|
504
|
+
# optimization_strategy controls model selection:
|
|
505
|
+
# "performance" — pick the most capable model
|
|
506
|
+
# "cost" — pick the cheapest model that meets quality
|
|
507
|
+
# "speed" — pick the lowest-latency model
|
|
508
|
+
# ─────────────────────────────────────────────
|
|
509
|
+
researcher_agent:
|
|
510
|
+
name: "researcher_agent"
|
|
511
|
+
agent_type: "llm"
|
|
512
|
+
description: "Researches topics using tools and memory context"
|
|
513
|
+
model: "gpt-4o-mini"
|
|
514
|
+
temperature: 0.5
|
|
515
|
+
max_tokens: 1500
|
|
516
|
+
communication_type: "chain"
|
|
517
|
+
optimization_strategy: "performance"
|
|
518
|
+
reasoning: true # SDK chain-of-thought tool injection
|
|
519
|
+
thinking: true # Native model thinking for deep analysis
|
|
520
|
+
thinking_budget: 8192 # Max thinking tokens
|
|
521
|
+
enable_prompt_caching: true # Cache system prompt + tools (~90% savings on Anthropic)
|
|
522
|
+
|
|
523
|
+
# ── Smart memory (BRD-009) ──
|
|
524
|
+
# Dict form enables advanced memory strategies. No external deps — Redis only.
|
|
525
|
+
# "hybrid" blends recency + relevance scoring for context selection.
|
|
526
|
+
memory:
|
|
527
|
+
strategy: "hybrid" # "recency" | "relevance" | "hybrid"
|
|
528
|
+
limit: 10 # Max feed posts to load per invocation
|
|
529
|
+
cross_session: true # Persist memory across sessions
|
|
530
|
+
cross_session_limit: 50 # Max cross-session posts to retain
|
|
531
|
+
relevance_weight: 0.6 # Weight for relevance scoring (0.0-1.0)
|
|
532
|
+
recency_weight: 0.4 # Weight for recency scoring (0.0-1.0)
|
|
533
|
+
decay_hours: 24 # Hours before old entries decay
|
|
534
|
+
|
|
535
|
+
prompt: |
|
|
536
|
+
You are a research analyst. Analyze the provided data thoroughly.
|
|
537
|
+
Use available tools to gather additional information.
|
|
538
|
+
Return structured findings with confidence scores.
|
|
539
|
+
|
|
540
|
+
yields:
|
|
541
|
+
findings: "list"
|
|
542
|
+
query: "string"
|
|
543
|
+
analysis: "object"
|
|
544
|
+
report: "object"
|
|
545
|
+
status: "string"
|
|
546
|
+
|
|
547
|
+
inputs:
|
|
548
|
+
research_topic: "string"
|
|
549
|
+
processed_data: "object"
|
|
550
|
+
|
|
551
|
+
# Tools: specific tools + entire category
|
|
552
|
+
tools: ["math_eval", "timestamp", "sensitive_data_lookup"]
|
|
553
|
+
tool_categories: ["data"]
|
|
554
|
+
tool_choice: "auto"
|
|
555
|
+
allow_parallel_tool_calls: true
|
|
556
|
+
max_tool_calls_per_message: 10
|
|
557
|
+
# tool_call_timeout: 30
|
|
558
|
+
# auto_store_response: true
|
|
559
|
+
# auto_store_yields: true
|
|
560
|
+
|
|
561
|
+
can_call:
|
|
562
|
+
- agent: "advisor_agent"
|
|
563
|
+
|
|
564
|
+
# ─────────────────────────────────────────────
|
|
565
|
+
# PROGRAMMATIC AGENT — Fast fallback researcher (no LLM)
|
|
566
|
+
# auto_discover matches fallback_researcher_agent() in agency/fallback_researcher_agent.py
|
|
567
|
+
#
|
|
568
|
+
# Race pattern: runs instantly while researcher_agent waits for LLM.
|
|
569
|
+
# advisor_agent's OR fan-in resolves as soon as this completes.
|
|
570
|
+
# ─────────────────────────────────────────────
|
|
571
|
+
fallback_researcher_agent:
|
|
572
|
+
name: "fallback_researcher_agent"
|
|
573
|
+
agent_type: "programmatic"
|
|
574
|
+
description: "Fast template-based research fallback — instant, no LLM"
|
|
575
|
+
communication_type: "chain"
|
|
576
|
+
|
|
577
|
+
yields:
|
|
578
|
+
findings: "list"
|
|
579
|
+
query: "string"
|
|
580
|
+
analysis: "object"
|
|
581
|
+
report: "object"
|
|
582
|
+
status: "string"
|
|
583
|
+
|
|
584
|
+
inputs:
|
|
585
|
+
processed_data: "object"
|
|
586
|
+
|
|
587
|
+
can_call:
|
|
588
|
+
- agent: "advisor_agent"
|
|
589
|
+
|
|
590
|
+
# ─────────────────────────────────────────────
|
|
591
|
+
# LLM AGENT — @chain + @compose (fan-in advisor)
|
|
592
|
+
# auto_discover matches advisor_agent() in agency/advisor_agent.py
|
|
593
|
+
#
|
|
594
|
+
# Flow: waits for processor AND researcher → LLM analyzes →
|
|
595
|
+
# @compose shapes output → @chain validates + scores
|
|
596
|
+
# ─────────────────────────────────────────────
|
|
597
|
+
advisor_agent:
|
|
598
|
+
name: "advisor_agent"
|
|
599
|
+
agent_type: "llm"
|
|
600
|
+
description: "Analyzes upstream results and produces actionable recommendations"
|
|
601
|
+
model: "gpt-4o-mini"
|
|
602
|
+
temperature: 0.3
|
|
603
|
+
max_tokens: 1000
|
|
604
|
+
communication_type: "chain"
|
|
605
|
+
optimization_strategy: "performance"
|
|
606
|
+
|
|
607
|
+
# ── Fan-in with OR expression ──
|
|
608
|
+
# Waits for processor AND whichever research agent finishes first.
|
|
609
|
+
# The fallback_researcher_agent is instant (programmatic), so this
|
|
610
|
+
# typically resolves before researcher_agent's LLM call completes.
|
|
611
|
+
#
|
|
612
|
+
# Supported wait_for patterns:
|
|
613
|
+
# "A AND B" — waits for both A and B
|
|
614
|
+
# "A OR B" — waits for either A or B (first wins)
|
|
615
|
+
# "A AND B?" — A required, B optional
|
|
616
|
+
# "A AND (B OR C)" — A required + first of B or C (used here)
|
|
617
|
+
# "A AND (B OR C) AND D?" — A required + first of B/C + D optional
|
|
618
|
+
# When called from processor_agent chain: waits for processor + research
|
|
619
|
+
# When called from scheduler_agent: no wait_for needed (single upstream)
|
|
620
|
+
# The SDK evaluates wait_for only when multiple upstreams are pending.
|
|
621
|
+
wait_for: "processor_agent AND (researcher_agent OR fallback_researcher_agent)"
|
|
622
|
+
wait_for_timeout: 120
|
|
623
|
+
|
|
624
|
+
prompt: |
|
|
625
|
+
You are a strategic advisor. Analyze the processed data and research
|
|
626
|
+
findings provided. Produce actionable recommendations with priority
|
|
627
|
+
scoring. Identify risks and suggest concrete next steps.
|
|
628
|
+
|
|
629
|
+
yields:
|
|
630
|
+
recommendations: "list"
|
|
631
|
+
risk_assessment: "string"
|
|
632
|
+
priority_score: "number"
|
|
633
|
+
next_steps: "list"
|
|
634
|
+
status: "string"
|
|
635
|
+
|
|
636
|
+
# Strict yields contract — Manager auto-retries (with feedback) when the
|
|
637
|
+
# advisor's output doesn't match the schema above. Each retry sees the
|
|
638
|
+
# previous (wrong) output + validation errors as _rerun_context so the
|
|
639
|
+
# LLM can self-correct. After enforce_yields_retry attempts, the
|
|
640
|
+
# Manager escalates instead of looping forever.
|
|
641
|
+
# enforce_yields: true
|
|
642
|
+
# enforce_yields_retry: 2
|
|
643
|
+
|
|
644
|
+
inputs:
|
|
645
|
+
processed_data: "object"
|
|
646
|
+
research_findings: "object"
|
|
647
|
+
|
|
648
|
+
# auto_store_response: true
|
|
649
|
+
# auto_store_yields: true
|
|
650
|
+
|
|
651
|
+
# ─────────────────────────────────────────────
|
|
652
|
+
# SCHEDULED AGENT — Cron wake_up + on-demand entry point
|
|
653
|
+
# auto_discover matches scheduler_agent() in agency/scheduler_agent.py
|
|
654
|
+
# Runs daily at 9 AM UTC AND via mesh_call("scheduled_report", data)
|
|
655
|
+
# Chains output to advisor_agent for LLM-powered analysis
|
|
656
|
+
# ─────────────────────────────────────────────
|
|
657
|
+
scheduler_agent:
|
|
658
|
+
name: "scheduler_agent"
|
|
659
|
+
agent_type: "programmatic"
|
|
660
|
+
description: "Generates periodic status reports and chains to advisor for analysis"
|
|
661
|
+
communication_type: "chain" # Chain output to downstream agents
|
|
662
|
+
wake_up: "0 9 * * *" # Every day at 9 AM UTC
|
|
663
|
+
|
|
664
|
+
yields:
|
|
665
|
+
report: "string"
|
|
666
|
+
generated_at: "string"
|
|
667
|
+
checks: "object"
|
|
668
|
+
metrics: "object"
|
|
669
|
+
status: "string"
|
|
670
|
+
|
|
671
|
+
inputs:
|
|
672
|
+
trigger: "string"
|
|
673
|
+
|
|
674
|
+
# memory: false # Enable if scheduler needs historical context
|
|
675
|
+
# auto_store_response: true
|
|
676
|
+
# auto_store_yields: true
|
|
677
|
+
|
|
678
|
+
# Chain scheduled reports to advisor for analysis
|
|
679
|
+
can_call:
|
|
680
|
+
- agent: "advisor_agent"
|
|
681
|
+
condition: "calling_agent_response.status == 'report_generated'"
|
|
682
|
+
|
|
683
|
+
# ═══════════════════════════════════════════════════
|
|
684
|
+
# EXTERNAL AGENTS (uncomment when framework is installed)
|
|
685
|
+
# One agent = one specific action/workflow/graph.
|
|
686
|
+
# Create multiple agents with different connector_config for multiple workflows.
|
|
687
|
+
# See agency/external_agents.py for Python implementations
|
|
688
|
+
# ═══════════════════════════════════════════════════
|
|
689
|
+
|
|
690
|
+
# ─── CrewAI ───
|
|
691
|
+
# crewai_research:
|
|
692
|
+
# name: "crewai_research"
|
|
693
|
+
# agent_type: "external"
|
|
694
|
+
# framework: "crewai"
|
|
695
|
+
# description: "Delegates research to a CrewAI crew"
|
|
696
|
+
# connector_config:
|
|
697
|
+
# endpoint: "${CREWAI_ENDPOINT:http://localhost:9000}" # Required
|
|
698
|
+
# api_key: "${CREWAI_API_KEY:}" # Bearer Token
|
|
699
|
+
# # user_api_key: "${CREWAI_USER_API_KEY:}" # User Bearer Token (preferred over api_key)
|
|
700
|
+
# # poll_interval: 2.0 # Seconds between status polls (default: 2.0)
|
|
701
|
+
# # max_poll_seconds: 300.0 # Max total polling time (default: 300)
|
|
702
|
+
# # http_timeout: 30.0 # HTTP request timeout (default: 30)
|
|
703
|
+
# yields:
|
|
704
|
+
# research_result: "string"
|
|
705
|
+
# sources: "list"
|
|
706
|
+
# can_call:
|
|
707
|
+
# - agent: "advisor_agent"
|
|
708
|
+
|
|
709
|
+
# ─── LangGraph ───
|
|
710
|
+
# langgraph_workflow:
|
|
711
|
+
# name: "langgraph_workflow"
|
|
712
|
+
# agent_type: "external"
|
|
713
|
+
# framework: "langgraph"
|
|
714
|
+
# description: "Runs a LangGraph stateful workflow"
|
|
715
|
+
# connector_config:
|
|
716
|
+
# endpoint: "${LANGGRAPH_ENDPOINT:http://localhost:8123}" # Required
|
|
717
|
+
# api_key: "${LANGCHAIN_API_KEY:}"
|
|
718
|
+
# graph_id: "my_graph" # Workflow selector — which graph to run (default: "agent")
|
|
719
|
+
# # poll_interval: 1.0
|
|
720
|
+
# # max_poll_seconds: 300.0
|
|
721
|
+
# # http_timeout: 30.0
|
|
722
|
+
# yields:
|
|
723
|
+
# workflow_result: "object"
|
|
724
|
+
|
|
725
|
+
# ─── AutoGen ───
|
|
726
|
+
# autogen_team:
|
|
727
|
+
# name: "autogen_team"
|
|
728
|
+
# agent_type: "external"
|
|
729
|
+
# framework: "autogen"
|
|
730
|
+
# description: "Multi-agent conversation via external AutoGen Studio"
|
|
731
|
+
# connector_config:
|
|
732
|
+
# endpoint: "http://localhost:8081" # AutoGen Studio or custom API URL
|
|
733
|
+
# # api_key: "${AUTOGEN_API_KEY:}" # Bearer token (optional)
|
|
734
|
+
# # workflow_id: "" # Workflow/agent ID to execute
|
|
735
|
+
# # timeout: 120 # HTTP request timeout (seconds)
|
|
736
|
+
# # poll_interval: 2 # Seconds between status polls
|
|
737
|
+
# # max_poll_seconds: 300 # Max total polling time
|
|
738
|
+
# yields:
|
|
739
|
+
# team_result: "string"
|
|
740
|
+
|
|
741
|
+
# ─── A2A (Agent-to-Agent Protocol) ───
|
|
742
|
+
# a2a_partner:
|
|
743
|
+
# name: "a2a_partner"
|
|
744
|
+
# agent_type: "external"
|
|
745
|
+
# framework: "a2a"
|
|
746
|
+
# description: "Communicates with an A2A-compatible agent"
|
|
747
|
+
# connector_config:
|
|
748
|
+
# url: "${A2A_AGENT_URL:http://partner-agent:8080}" # Required (use 'url', not 'endpoint')
|
|
749
|
+
# auth_token: "${A2A_AUTH_TOKEN:}"
|
|
750
|
+
# # auth_scheme: "Bearer" # Authorization header scheme (default: "Bearer")
|
|
751
|
+
# # poll_interval: 2.0
|
|
752
|
+
# # max_poll_seconds: 300.0
|
|
753
|
+
# # http_timeout: 30.0
|
|
754
|
+
# yields:
|
|
755
|
+
# partner_response: "object"
|
|
756
|
+
|
|
757
|
+
# ─── MCP (Model Context Protocol) ─── http transport
|
|
758
|
+
# mcp_http_tool:
|
|
759
|
+
# name: "mcp_http_tool"
|
|
760
|
+
# agent_type: "external"
|
|
761
|
+
# framework: "mcp"
|
|
762
|
+
# description: "Access tools from an MCP server via HTTP"
|
|
763
|
+
# connector_config:
|
|
764
|
+
# tool_name: "my_tool" # Required: name of the tool to call
|
|
765
|
+
# transport: "http" # "http" or "stdio"
|
|
766
|
+
# url: "${MCP_ENDPOINT:http://localhost:5000}" # MCP server URL (use 'url', not 'endpoint')
|
|
767
|
+
# auth_token: "${MCP_API_KEY:}"
|
|
768
|
+
# # timeout: 60.0
|
|
769
|
+
# yields:
|
|
770
|
+
# tool_results: "object"
|
|
771
|
+
|
|
772
|
+
# ─── MCP (Model Context Protocol) ─── stdio transport
|
|
773
|
+
# mcp_stdio_tool:
|
|
774
|
+
# name: "mcp_stdio_tool"
|
|
775
|
+
# agent_type: "external"
|
|
776
|
+
# framework: "mcp"
|
|
777
|
+
# description: "Access tools from a local MCP server via stdio"
|
|
778
|
+
# connector_config:
|
|
779
|
+
# tool_name: "my_tool" # Required: name of the tool to call
|
|
780
|
+
# transport: "stdio"
|
|
781
|
+
# command: "npx" # Executable to launch
|
|
782
|
+
# args: ["-y", "@mcp/server-npm"] # Command arguments
|
|
783
|
+
# # env: # Environment variables for subprocess
|
|
784
|
+
# # MY_VAR: "value"
|
|
785
|
+
# # timeout: 60.0
|
|
786
|
+
# yields:
|
|
787
|
+
# tool_results: "object"
|
|
788
|
+
|
|
789
|
+
# ─── Zapier ───
|
|
790
|
+
# zapier_sheets:
|
|
791
|
+
# name: "zapier_sheets"
|
|
792
|
+
# agent_type: "external"
|
|
793
|
+
# framework: "zapier"
|
|
794
|
+
# description: "Trigger Zapier actions — MCP path (prefer_mcp=true) or REST fallback"
|
|
795
|
+
# connector_config:
|
|
796
|
+
# connection: "google_sheets" # App name (connection + action = tool name)
|
|
797
|
+
# action: "create_row" # Action to perform — workflow selector
|
|
798
|
+
# mcp_key: "${ZAPIER_MCP_KEY:}" # MCP path (preferred)
|
|
799
|
+
# api_key: "${ZAPIER_API_KEY:}" # REST fallback
|
|
800
|
+
# # prefer_mcp: true # Try MCP first, fall back to REST (default: true)
|
|
801
|
+
# # instructions: "" # Natural language instructions (REST path only)
|
|
802
|
+
# # timeout: 60.0
|
|
803
|
+
# yields:
|
|
804
|
+
# action_result: "object"
|
|
805
|
+
|
|
806
|
+
# ─── Composio ───
|
|
807
|
+
# composio_github:
|
|
808
|
+
# name: "composio_github"
|
|
809
|
+
# agent_type: "external"
|
|
810
|
+
# framework: "composio"
|
|
811
|
+
# description: "Access Composio-managed integrations"
|
|
812
|
+
# connector_config:
|
|
813
|
+
# action: "GITHUB_STAR_A_REPOSITORY" # Required: single Composio action — workflow selector
|
|
814
|
+
# entity_id: "default" # User/entity to act on behalf of
|
|
815
|
+
# api_key: "${COMPOSIO_API_KEY:}"
|
|
816
|
+
# # timeout: 60.0
|
|
817
|
+
# yields:
|
|
818
|
+
# integration_result: "object"
|
|
819
|
+
|
|
820
|
+
# ─── n8n ───
|
|
821
|
+
# n8n_workflow:
|
|
822
|
+
# name: "n8n_workflow"
|
|
823
|
+
# agent_type: "external"
|
|
824
|
+
# framework: "n8n"
|
|
825
|
+
# description: "Trigger n8n workflows via webhook"
|
|
826
|
+
# connector_config:
|
|
827
|
+
# webhook_url: "${N8N_WEBHOOK_URL:}" # Required — each workflow has its own URL
|
|
828
|
+
# auth_token: "${N8N_AUTH_TOKEN:}"
|
|
829
|
+
# # timeout: 60.0 # HTTP timeout (sync mode only)
|
|
830
|
+
# # mode: "sync" # "sync" (default) or "callback"
|
|
831
|
+
# # callback_timeout: 120.0 # Seconds to wait for callback (callback mode only)
|
|
832
|
+
# yields:
|
|
833
|
+
# workflow_result: "object"
|
|
834
|
+
#
|
|
835
|
+
# n8n + callback mode:
|
|
836
|
+
# Use mode: "callback" when n8n workflow uses "Respond Immediately".
|
|
837
|
+
# LeafMesh injects _leafmesh_callback_url + _leafmesh_session_id into payload.
|
|
838
|
+
# n8n workflow should end with HTTP Request node POSTing result back to that URL.
|
|
839
|
+
#
|
|
840
|
+
# n8n_async_workflow:
|
|
841
|
+
# name: "n8n_async_workflow"
|
|
842
|
+
# agent_type: "external"
|
|
843
|
+
# framework: "n8n"
|
|
844
|
+
# description: "Long-running n8n workflow with async callback"
|
|
845
|
+
# connector_config:
|
|
846
|
+
# webhook_url: "${N8N_WEBHOOK_URL:}"
|
|
847
|
+
# mode: "callback"
|
|
848
|
+
# callback_timeout: 300.0 # 5 min — workflow takes time to process
|
|
849
|
+
# yields:
|
|
850
|
+
# workflow_result: "object"
|
|
851
|
+
|
|
852
|
+
# ═══════════════════════════════════════════════════
|
|
853
|
+
# PROGRAMMATIC + INTEGRATION AGENTS
|
|
854
|
+
# Same connectors as external agents but paired with Python intelligence.
|
|
855
|
+
# SDK reads connector_config in the same way — pass connection details here.
|
|
856
|
+
# One agent = one specific action/workflow.
|
|
857
|
+
# ═══════════════════════════════════════════════════
|
|
858
|
+
|
|
859
|
+
# ─── Zapier (programmatic) ───
|
|
860
|
+
# zapier_sheets:
|
|
861
|
+
# name: "zapier_sheets"
|
|
862
|
+
# agent_type: "programmatic"
|
|
863
|
+
# description: "Adds a row to Google Sheets via Zapier"
|
|
864
|
+
# communication_type: "chain"
|
|
865
|
+
# integration: "zapier" # Options: zapier | composio | n8n | mcp
|
|
866
|
+
# connector_config:
|
|
867
|
+
# connection: "google_sheets" # Zapier app name ┐ combined into
|
|
868
|
+
# action: "create_row" # Zapier action ┘ google_sheets_create_row
|
|
869
|
+
# mcp_key: "${ZAPIER_MCP_KEY:}" # MCP path (preferred)
|
|
870
|
+
# api_key: "${ZAPIER_API_KEY:}" # REST fallback
|
|
871
|
+
# # prefer_mcp: true
|
|
872
|
+
# # instructions: ""
|
|
873
|
+
# # timeout: 60.0
|
|
874
|
+
# yields:
|
|
875
|
+
# result: "object"
|
|
876
|
+
|
|
877
|
+
# ─── Composio (programmatic) ───
|
|
878
|
+
# composio_github:
|
|
879
|
+
# name: "composio_github"
|
|
880
|
+
# agent_type: "programmatic"
|
|
881
|
+
# description: "Stars a GitHub repo via Composio"
|
|
882
|
+
# communication_type: "chain"
|
|
883
|
+
# integration: "composio"
|
|
884
|
+
# connector_config:
|
|
885
|
+
# action: "GITHUB_STAR_A_REPOSITORY" # Required: Composio action enum (UPPERCASE)
|
|
886
|
+
# entity_id: "default" # User/entity context
|
|
887
|
+
# api_key: "${COMPOSIO_API_KEY:}"
|
|
888
|
+
# # timeout: 60.0
|
|
889
|
+
# yields:
|
|
890
|
+
# result: "object"
|
|
891
|
+
|
|
892
|
+
# ─── n8n (programmatic) ───
|
|
893
|
+
# n8n_notify:
|
|
894
|
+
# name: "n8n_notify"
|
|
895
|
+
# agent_type: "programmatic"
|
|
896
|
+
# description: "Triggers an n8n workflow via webhook"
|
|
897
|
+
# communication_type: "chain"
|
|
898
|
+
# integration: "n8n"
|
|
899
|
+
# connector_config:
|
|
900
|
+
# webhook_url: "${N8N_WEBHOOK_URL:}" # Required — each workflow has its own URL
|
|
901
|
+
# auth_token: "${N8N_AUTH_TOKEN:}"
|
|
902
|
+
# # timeout: 60.0
|
|
903
|
+
# # mode: "callback" # Use callback for async/long-running workflows
|
|
904
|
+
# # callback_timeout: 120.0
|
|
905
|
+
# yields:
|
|
906
|
+
# result: "object"
|
|
907
|
+
|
|
908
|
+
# ─── MCP (programmatic) ─── http transport
|
|
909
|
+
# mcp_search:
|
|
910
|
+
# name: "mcp_search"
|
|
911
|
+
# agent_type: "programmatic"
|
|
912
|
+
# description: "Calls a specific tool on an MCP server"
|
|
913
|
+
# communication_type: "chain"
|
|
914
|
+
# integration: "mcp"
|
|
915
|
+
# connector_config:
|
|
916
|
+
# tool_name: "web_search" # Required: tool to invoke
|
|
917
|
+
# transport: "http" # "http" or "stdio"
|
|
918
|
+
# url: "${MCP_ENDPOINT:http://localhost:5000}" # MCP server URL
|
|
919
|
+
# auth_token: "${MCP_API_KEY:}"
|
|
920
|
+
# # timeout: 60.0
|
|
921
|
+
# yields:
|
|
922
|
+
# result: "object"
|
|
923
|
+
|
|
924
|
+
# ─── MCP (programmatic) ─── stdio transport
|
|
925
|
+
# mcp_local:
|
|
926
|
+
# name: "mcp_local"
|
|
927
|
+
# agent_type: "programmatic"
|
|
928
|
+
# description: "Calls a tool on a local MCP server via stdio"
|
|
929
|
+
# communication_type: "chain"
|
|
930
|
+
# integration: "mcp"
|
|
931
|
+
# connector_config:
|
|
932
|
+
# tool_name: "my_tool" # Required: tool to invoke
|
|
933
|
+
# transport: "stdio"
|
|
934
|
+
# command: "npx"
|
|
935
|
+
# args: ["-y", "@mcp/server-npm"]
|
|
936
|
+
# # env:
|
|
937
|
+
# # MY_VAR: "value"
|
|
938
|
+
# # timeout: 60.0
|
|
939
|
+
# yields:
|
|
940
|
+
# result: "object"
|
|
941
|
+
|
|
942
|
+
# ═══════════════════════════════════════════════════
|
|
943
|
+
# DATA STRUCTURES — Custom data type definitions (optional)
|
|
944
|
+
# Define shared schemas that agents can reference for validation
|
|
945
|
+
# ═══════════════════════════════════════════════════
|
|
946
|
+
# data_structures:
|
|
947
|
+
# customer_profile:
|
|
948
|
+
# type: "object"
|
|
949
|
+
# properties:
|
|
950
|
+
# name: { type: "string" }
|
|
951
|
+
# email: { type: "string" }
|
|
952
|
+
# tier: { type: "string" }
|
|
953
|
+
# required: ["name", "email"]
|
|
954
|
+
# validation_rules:
|
|
955
|
+
# email: "email_format"
|
|
956
|
+
# order_item:
|
|
957
|
+
# type: "object"
|
|
958
|
+
# properties:
|
|
959
|
+
# product_id: { type: "string" }
|
|
960
|
+
# quantity: { type: "number" }
|
|
961
|
+
# price: { type: "number" }
|
|
962
|
+
# required: ["product_id", "quantity"]
|
|
963
|
+
|
|
964
|
+
# Self-healing is always enabled (core safety feature, no config needed)
|
|
965
|
+
|
|
966
|
+
# ═══════════════════════════════════════════════════
|
|
967
|
+
# EVOLUTION — Genetic algorithm optimization
|
|
968
|
+
# Set enabled: true and provide test_scenarios to auto-run on start()
|
|
969
|
+
# Or call leafmesh.evolve_mesh_architecture(scenarios) at runtime
|
|
970
|
+
# ═══════════════════════════════════════════════════
|
|
971
|
+
# evolution:
|
|
972
|
+
# enabled: true
|
|
973
|
+
# strategy: "genetic"
|
|
974
|
+
# population_size: 10
|
|
975
|
+
# generations: 50
|
|
976
|
+
# mutation_rate: 0.1
|
|
977
|
+
# crossover_rate: 0.7
|
|
978
|
+
# elite_size: 2
|
|
979
|
+
# mutation_types:
|
|
980
|
+
# - "prompt_variation"
|
|
981
|
+
# - "temperature_adjustment"
|
|
982
|
+
# - "tool_selection"
|
|
983
|
+
# fitness_function: "task_completion_rate"
|
|
984
|
+
# selection_method: "tournament"
|
|
985
|
+
# test_scenarios: []
|
|
986
|
+
|
|
987
|
+
# ═══════════════════════════════════════════════════
|
|
988
|
+
# OBSERVABILITY
|
|
989
|
+
#
|
|
990
|
+
# Observability auto-enables when LEAFMESH_LICENSE_KEY is set in .env.
|
|
991
|
+
# No YAML config needed — traces, metrics, and logs flow automatically.
|
|
992
|
+
# Set LEAFMESH_ENV_TOKEN in .env to group telemetry by environment.
|
|
993
|
+
# ═══════════════════════════════════════════════════
|
|
994
|
+
|
|
995
|
+
# ═══════════════════════════════════════════════════
|
|
996
|
+
# API ENDPOINTS (built-in, no config needed)
|
|
997
|
+
#
|
|
998
|
+
# Trigger workflows:
|
|
999
|
+
# POST /api/mesh/request — trigger agent workflow via entry point
|
|
1000
|
+
# POST /api/mesh/stream — SSE stream of LLM response via entry point
|
|
1001
|
+
# GET /api/mesh/entry_points — list available entry points
|
|
1002
|
+
#
|
|
1003
|
+
# Webhooks (HITL + external integrations):
|
|
1004
|
+
# POST /webhook/{entry_point} — new task OR resume human HITL response
|
|
1005
|
+
# GET /api/webhook/secret — HMAC signing secret for webhook auth
|
|
1006
|
+
#
|
|
1007
|
+
# Sessions:
|
|
1008
|
+
# POST /api/sessions/{session_id}/agents/{agent_name}/rerun
|
|
1009
|
+
# — re-run an agent in an existing session
|
|
1010
|
+
# with optional feedback / new input
|
|
1011
|
+
# (used by ADK Studio "Rerun" button;
|
|
1012
|
+
# mirrors sdk.rerun_agent in Python)
|
|
1013
|
+
#
|
|
1014
|
+
# Native channel adapters (registered when channels: is configured on a human agent):
|
|
1015
|
+
# POST /channels/slack/{agent}/events — Slack Events API
|
|
1016
|
+
# POST /channels/telegram/{agent}/webhook — Telegram Bot updates
|
|
1017
|
+
# POST /channels/discord/{agent}/interactions — Discord interactions
|
|
1018
|
+
# GET /channels/whatsapp/{agent}/webhook — WhatsApp webhook verification
|
|
1019
|
+
# POST /channels/whatsapp/{agent}/webhook — WhatsApp messages
|
|
1020
|
+
# POST /channels/teams/{agent}/messages — Microsoft Teams activities
|
|
1021
|
+
#
|
|
1022
|
+
# Config validation:
|
|
1023
|
+
# POST /api/yaml/validate — validate a full config body (for editors)
|
|
1024
|
+
#
|
|
1025
|
+
# System:
|
|
1026
|
+
# GET /health — health check
|
|
1027
|
+
# GET /docs — interactive API docs (ReDoc)
|
|
1028
|
+
# ═══════════════════════════════════════════════════
|