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,492 @@
|
|
|
1
|
+
# LeafMesh SDK — Complete Reference
|
|
2
|
+
|
|
3
|
+
## SDK Public Methods
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
from leafmesh import LeafMesh
|
|
7
|
+
|
|
8
|
+
# Initialization
|
|
9
|
+
sdk = LeafMesh.from_yaml("configs/config.yaml") # From YAML file
|
|
10
|
+
sdk = LeafMesh.from_dict(config_dict) # From Python dict
|
|
11
|
+
sdk = LeafMesh(config=LeafMeshConfig(...)) # Direct instantiation
|
|
12
|
+
|
|
13
|
+
# Lifecycle
|
|
14
|
+
await sdk.start() # Initialize everything
|
|
15
|
+
await sdk.stop() # Graceful shutdown
|
|
16
|
+
async with sdk as mesh: # Context manager
|
|
17
|
+
|
|
18
|
+
# Core execution
|
|
19
|
+
result = await sdk.mesh_call(
|
|
20
|
+
entry_point_name="greet",
|
|
21
|
+
input_data={"message": "Hello"},
|
|
22
|
+
session_id="optional-session-id", # Auto-generated if omitted
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Re-run a single agent inside an existing session (1.0.299+)
|
|
26
|
+
# Routes through Manager.execute_state — same conductor as strict yields enforcement.
|
|
27
|
+
result = await sdk.rerun_agent(
|
|
28
|
+
agent_name="advisor_agent",
|
|
29
|
+
session_id="sess-123",
|
|
30
|
+
feedback={"error": "missing action_items"}, # optional; merged as _rerun_context
|
|
31
|
+
reason="user_request", # optional audit string
|
|
32
|
+
new_input={"x": 1}, # optional; falls back to auto_store_agent_input
|
|
33
|
+
)
|
|
34
|
+
# Returns: {"status": "dispatched", "agent": ..., "session_id": ..., "input_source": ..., "reason": ...}
|
|
35
|
+
# Same primitive is exposed at POST /api/sessions/{session_id}/agents/{agent_name}/rerun
|
|
36
|
+
|
|
37
|
+
# Agent registration (alternative to auto-discover)
|
|
38
|
+
@sdk("agent_name")
|
|
39
|
+
async def agent_name(llm_response, input_data, context):
|
|
40
|
+
return {"result": llm_response}
|
|
41
|
+
|
|
42
|
+
# Auto-discover agents from directory
|
|
43
|
+
sdk.discover(directory="./agency", pattern="*_agent.py", recursive=False)
|
|
44
|
+
|
|
45
|
+
# Ad-hoc LLM calls (outside agent context)
|
|
46
|
+
result = await sdk.call_llm(
|
|
47
|
+
prompt="Analyze this data",
|
|
48
|
+
session_id="sess-123",
|
|
49
|
+
model="gpt-4o",
|
|
50
|
+
system_prompt="You are a data analyst",
|
|
51
|
+
temperature=0.2,
|
|
52
|
+
max_tokens=1000,
|
|
53
|
+
business_context="Financial analysis for Q3",
|
|
54
|
+
care_instructions="Be precise with numbers",
|
|
55
|
+
sentiment_guidance="Professional tone",
|
|
56
|
+
guardrails="Do not provide investment advice",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Analytics
|
|
60
|
+
analytics = await sdk.get_usage_analytics() # Aggregated usage stats
|
|
61
|
+
cache_stats = await sdk.get_llm_cache_stats() # LLM cache metrics
|
|
62
|
+
|
|
63
|
+
# Feed (cursor-based pagination, latest-first)
|
|
64
|
+
posts, next_cursor = await sdk.get_global_feed(count=100, cursor="+")
|
|
65
|
+
posts, next_cursor = await sdk.get_agent_feed("agent_name", count=50, cursor="+")
|
|
66
|
+
posts, next_cursor = await sdk.get_session_feed("session_id", count=50, cursor="+")
|
|
67
|
+
|
|
68
|
+
# Custom LLM provider
|
|
69
|
+
sdk.register_llm_provider(
|
|
70
|
+
name="mistral",
|
|
71
|
+
provider_class=MistralProvider,
|
|
72
|
+
model_prefixes=["mistral-", "codestral-"],
|
|
73
|
+
api_key="...",
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Self-healing
|
|
77
|
+
await sdk.enable_self_healing()
|
|
78
|
+
health = await sdk.get_agent_health_status(agent_id)
|
|
79
|
+
stats = await sdk.get_healing_statistics()
|
|
80
|
+
|
|
81
|
+
# Evolution
|
|
82
|
+
await sdk.evolve_mesh_architecture(test_scenarios=[...])
|
|
83
|
+
stats = await sdk.get_evolution_statistics()
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Full Config YAML Structure
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
# ── Top-level ──
|
|
90
|
+
name: "my_mesh"
|
|
91
|
+
version: "1.0.0"
|
|
92
|
+
architecture: "managed_mesh" # Only supported type
|
|
93
|
+
environment: "development" # development | production
|
|
94
|
+
debug: false
|
|
95
|
+
log_level: "INFO" # DEBUG | INFO | WARNING | ERROR
|
|
96
|
+
|
|
97
|
+
# ── Redis ──
|
|
98
|
+
redis:
|
|
99
|
+
host: "localhost"
|
|
100
|
+
port: 6379
|
|
101
|
+
db: 0
|
|
102
|
+
password: null
|
|
103
|
+
decode_responses: true
|
|
104
|
+
auto_storage: true
|
|
105
|
+
default_ttl: 3600
|
|
106
|
+
session_ttl: 7200
|
|
107
|
+
cluster_mode: false
|
|
108
|
+
cluster_nodes: []
|
|
109
|
+
|
|
110
|
+
# ── Auto-discover ──
|
|
111
|
+
auto_discover:
|
|
112
|
+
directory: "./agency"
|
|
113
|
+
pattern: "*_agent.py"
|
|
114
|
+
recursive: false
|
|
115
|
+
|
|
116
|
+
# ── Manager (coordination + summarizer) ──
|
|
117
|
+
manager:
|
|
118
|
+
enabled: true
|
|
119
|
+
model: "gpt-4o-mini" # Model for summarizer LLM calls
|
|
120
|
+
domain: "generic" # Summarizer domain specialization
|
|
121
|
+
can_intervene: true # Allow automatic interventions
|
|
122
|
+
health_check_interval: 60 # Seconds between health checks
|
|
123
|
+
agent_timeout_threshold: 180 # Seconds before agent timeout
|
|
124
|
+
chain_completion_timeout: 60.0 # Seconds for can_call chain completeness
|
|
125
|
+
coordination_rules: {} # Custom business rules
|
|
126
|
+
human_input_rules:
|
|
127
|
+
max_concurrent_requests: 3
|
|
128
|
+
max_agent_requests: 5
|
|
129
|
+
enable_request_queuing: true
|
|
130
|
+
timeout_rules:
|
|
131
|
+
max_timeouts_before_escalation: 2
|
|
132
|
+
timeout_escalation_enabled: true
|
|
133
|
+
workflow_pause_rules:
|
|
134
|
+
max_pause_duration_minutes: 30
|
|
135
|
+
max_concurrent_paused_workflows: 2
|
|
136
|
+
|
|
137
|
+
# ── Mesh ──
|
|
138
|
+
mesh:
|
|
139
|
+
call_timeout: 30 # Default timeout for mesh calls
|
|
140
|
+
bedrock: # AWS Bedrock (optional)
|
|
141
|
+
region: "us-east-1"
|
|
142
|
+
profile: null # AWS profile name
|
|
143
|
+
endpoint_url: null
|
|
144
|
+
vertex: # Google Vertex AI (optional)
|
|
145
|
+
project: "my-gcp-project"
|
|
146
|
+
location: "us-central1"
|
|
147
|
+
foundry: # Azure AI Foundry (optional)
|
|
148
|
+
endpoint: "https://resource.openai.azure.com"
|
|
149
|
+
api_version: null
|
|
150
|
+
|
|
151
|
+
# ── Entry Points ──
|
|
152
|
+
entry_points:
|
|
153
|
+
- name: "greet_user"
|
|
154
|
+
target: "greeter_agent"
|
|
155
|
+
condition: "always"
|
|
156
|
+
|
|
157
|
+
# ── Agents ──
|
|
158
|
+
agents:
|
|
159
|
+
agent_name:
|
|
160
|
+
# ... (see SKILL.md for all fields)
|
|
161
|
+
|
|
162
|
+
# ── Data Structures ──
|
|
163
|
+
data_structures:
|
|
164
|
+
customer_record:
|
|
165
|
+
type: "object"
|
|
166
|
+
properties:
|
|
167
|
+
name: {type: "string"}
|
|
168
|
+
score: {type: "number"}
|
|
169
|
+
required: ["name"]
|
|
170
|
+
|
|
171
|
+
# ── Evolution ──
|
|
172
|
+
evolution:
|
|
173
|
+
enabled: false
|
|
174
|
+
strategy: "genetic" # genetic | particle_swarm | simulated_annealing
|
|
175
|
+
population_size: 20
|
|
176
|
+
generations: 50
|
|
177
|
+
mutation_rate: 0.1
|
|
178
|
+
crossover_rate: 0.7
|
|
179
|
+
elite_size: 2
|
|
180
|
+
fitness_function: "task_completion_rate"
|
|
181
|
+
selection_method: "tournament"
|
|
182
|
+
test_scenarios: []
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Condition Syntax (can_call conditions)
|
|
186
|
+
|
|
187
|
+
Conditions evaluate the upstream agent's output data:
|
|
188
|
+
|
|
189
|
+
```yaml
|
|
190
|
+
can_call:
|
|
191
|
+
- agent: "specialist"
|
|
192
|
+
condition: "calling_agent_response.status == 'needs_specialist'"
|
|
193
|
+
- agent: "escalation"
|
|
194
|
+
condition: "calling_agent_response.priority == 'high'"
|
|
195
|
+
- agent: "greeter"
|
|
196
|
+
condition: "not calling_agent_response.from_agent" # Falsy check (HITL routing)
|
|
197
|
+
- agent: "processor"
|
|
198
|
+
condition: "calling_agent_response.from_agent == 'greeter_agent'"
|
|
199
|
+
- agent: "urgent_handler"
|
|
200
|
+
condition: "calling_agent_response.item_count > 0"
|
|
201
|
+
- agent: "default"
|
|
202
|
+
condition: "true" # Always matches (fallback)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Operators**: `==`, `!=`, `>`, `<`, `>=`, `<=`, `and`, `or`, `not`
|
|
206
|
+
**Access**: `calling_agent_response.field_name` for upstream agent output fields
|
|
207
|
+
|
|
208
|
+
### HITL output fields (available when human agent responds)
|
|
209
|
+
```
|
|
210
|
+
calling_agent_response.from_agent # Who called the human ("greeter_agent" or "")
|
|
211
|
+
calling_agent_response.human_message # What the human typed
|
|
212
|
+
calling_agent_response.human_decision # Human's decision field
|
|
213
|
+
calling_agent_response.human_data # Data from the human response
|
|
214
|
+
calling_agent_response.human_initiated # Always true for human output
|
|
215
|
+
calling_agent_response.source_agent # The human agent name
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## All Imports
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
# Core
|
|
222
|
+
from leafmesh import LeafMesh, LeafMeshConfig, AgentConfig, MeshConfig
|
|
223
|
+
from leafmesh import BedrockConfig, VertexConfig, FoundryConfig
|
|
224
|
+
from leafmesh import ChannelConfig, EscalationConfig, EscalationTarget
|
|
225
|
+
|
|
226
|
+
# Events & Sessions
|
|
227
|
+
from leafmesh import LeafMeshEvent, EventType, Session, SessionData
|
|
228
|
+
|
|
229
|
+
# Agents
|
|
230
|
+
from leafmesh import BaseAgent, AgentResponse
|
|
231
|
+
|
|
232
|
+
# Decorators
|
|
233
|
+
from leafmesh import pre_compose, chain, compose, conditional_chain, chain_with_results
|
|
234
|
+
|
|
235
|
+
# Tools
|
|
236
|
+
from leafmesh import tool, global_tool
|
|
237
|
+
|
|
238
|
+
# Integration helpers (for @pre_compose)
|
|
239
|
+
from leafmesh import zapier, mcp, composio, n8n
|
|
240
|
+
|
|
241
|
+
# Exceptions
|
|
242
|
+
from leafmesh import LeafMeshError, ConfigError, AgentError, RedisError, LeafMeshLicenseError
|
|
243
|
+
|
|
244
|
+
# Utilities
|
|
245
|
+
from leafmesh import LeafMeshLogger
|
|
246
|
+
from leafmesh import load_yaml_config, save_yaml_config, validate_config
|
|
247
|
+
from leafmesh import check_license_compliance, display_license_notice
|
|
248
|
+
|
|
249
|
+
# Advanced
|
|
250
|
+
from leafmesh import SelfHealingLeafMeshManager, AgentHealthStatus
|
|
251
|
+
from leafmesh import EvolutionaryLeafMeshOptimizer, LeafMeshGenome
|
|
252
|
+
from leafmesh import AdaptiveLLMExecutor, ModelSelectionStrategy
|
|
253
|
+
|
|
254
|
+
# LLM extensibility
|
|
255
|
+
from leafmesh import LLMProvider, LLMRequest, LLMResponse, StreamChunk
|
|
256
|
+
|
|
257
|
+
# Backwards compat (old names still work)
|
|
258
|
+
from leafmesh import SwarmSDK, SwarmConfig, SwarmEvent, SwarmError
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## External Connectors
|
|
262
|
+
|
|
263
|
+
### CrewAI
|
|
264
|
+
```yaml
|
|
265
|
+
agents:
|
|
266
|
+
crew_agent:
|
|
267
|
+
agent_type: "external"
|
|
268
|
+
framework: "crewai"
|
|
269
|
+
connector_config:
|
|
270
|
+
endpoint: "http://localhost:9000" # CrewAI hosted API
|
|
271
|
+
# api_key: "${CREWAI_API_KEY}" # Bearer Token
|
|
272
|
+
# user_api_key: "${CREWAI_USER_API_KEY}" # User Bearer Token (preferred over api_key)
|
|
273
|
+
# poll_interval: 2.0
|
|
274
|
+
# max_poll_seconds: 300
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### LangGraph
|
|
278
|
+
```yaml
|
|
279
|
+
agents:
|
|
280
|
+
graph_agent:
|
|
281
|
+
agent_type: "external"
|
|
282
|
+
framework: "langgraph"
|
|
283
|
+
connector_config:
|
|
284
|
+
endpoint: "http://localhost:8123" # LangGraph Platform URL
|
|
285
|
+
# api_key: "${LANGCHAIN_API_KEY}"
|
|
286
|
+
graph_id: "agent" # Which graph to run
|
|
287
|
+
# poll_interval: 1.0
|
|
288
|
+
# max_poll_seconds: 300
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### AutoGen
|
|
292
|
+
```yaml
|
|
293
|
+
agents:
|
|
294
|
+
autogen_agent:
|
|
295
|
+
agent_type: "external"
|
|
296
|
+
framework: "autogen"
|
|
297
|
+
connector_config:
|
|
298
|
+
endpoint: "http://localhost:8081" # AutoGen Studio or custom API
|
|
299
|
+
# api_key: "${AUTOGEN_API_KEY}"
|
|
300
|
+
# workflow_id: "my-workflow"
|
|
301
|
+
# timeout: 120
|
|
302
|
+
# poll_interval: 2.0
|
|
303
|
+
# max_poll_seconds: 300
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### A2A (Agent-to-Agent)
|
|
307
|
+
```yaml
|
|
308
|
+
agents:
|
|
309
|
+
a2a_agent:
|
|
310
|
+
agent_type: "external"
|
|
311
|
+
framework: "a2a"
|
|
312
|
+
connector_config:
|
|
313
|
+
url: "https://remote-agent.example.com" # A2A agent server URL
|
|
314
|
+
# auth_token: "${A2A_AUTH_TOKEN}"
|
|
315
|
+
# auth_scheme: "Bearer"
|
|
316
|
+
# poll_interval: 2.0
|
|
317
|
+
# max_poll_seconds: 300
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### MCP (Model Context Protocol)
|
|
321
|
+
```yaml
|
|
322
|
+
agents:
|
|
323
|
+
# HTTP transport — connects to remote MCP server
|
|
324
|
+
mcp_http_agent:
|
|
325
|
+
agent_type: "external"
|
|
326
|
+
framework: "mcp"
|
|
327
|
+
connector_config:
|
|
328
|
+
tool_name: "search" # Required — which tool to call
|
|
329
|
+
transport: "http"
|
|
330
|
+
url: "http://localhost:3000"
|
|
331
|
+
# auth_token: "${MCP_API_KEY}"
|
|
332
|
+
# timeout: 60
|
|
333
|
+
|
|
334
|
+
# stdio transport — launches local MCP server process
|
|
335
|
+
mcp_stdio_agent:
|
|
336
|
+
agent_type: "external"
|
|
337
|
+
framework: "mcp"
|
|
338
|
+
connector_config:
|
|
339
|
+
tool_name: "read_file" # Required — which tool to call
|
|
340
|
+
transport: "stdio"
|
|
341
|
+
command: "npx"
|
|
342
|
+
args: ["-y", "@mcp/server-filesystem"]
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Connector Execution Modes (all frameworks)
|
|
346
|
+
|
|
347
|
+
All connectors support two execution modes via `connector_config`:
|
|
348
|
+
|
|
349
|
+
| Field | Type | Default | Description |
|
|
350
|
+
|-------|------|---------|-------------|
|
|
351
|
+
| `mode` | string | `"sync"` | `"sync"` (wait for HTTP response) or `"callback"` (fire request, wait for external system to POST back) |
|
|
352
|
+
| `callback_timeout` | float | `120.0` | Seconds to wait for callback before timeout (callback mode only) |
|
|
353
|
+
|
|
354
|
+
**Callback mode**: The connector injects `_leafmesh_callback_url` and `_leafmesh_session_id` into the outbound payload. The external system processes async and POSTs the result back to `/callback/{agent_name}`.
|
|
355
|
+
|
|
356
|
+
```yaml
|
|
357
|
+
# n8n with callback mode (fire-and-forget workflow)
|
|
358
|
+
n8n_async:
|
|
359
|
+
agent_type: "external"
|
|
360
|
+
framework: "n8n"
|
|
361
|
+
connector_config:
|
|
362
|
+
webhook_url: "https://n8n.example.com/webhook/abc"
|
|
363
|
+
mode: "callback"
|
|
364
|
+
callback_timeout: 300
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Programmatic Integrations (Zapier, Composio, n8n, MCP)
|
|
368
|
+
|
|
369
|
+
`integration` is a **string** field (not a dict). Valid values: `"zapier"`, `"composio"`, `"n8n"`, `"mcp"`.
|
|
370
|
+
Only valid on `agent_type: "programmatic"`.
|
|
371
|
+
|
|
372
|
+
```yaml
|
|
373
|
+
agents:
|
|
374
|
+
zapier_agent:
|
|
375
|
+
agent_type: "programmatic"
|
|
376
|
+
integration: "zapier"
|
|
377
|
+
connector_config:
|
|
378
|
+
connection: "google_sheets" # Service name
|
|
379
|
+
action: "create_spreadsheet_row" # Action to execute
|
|
380
|
+
# mcp_key: "${ZAPIER_MCP_KEY}" # MCP path (preferred)
|
|
381
|
+
# api_key: "${ZAPIER_API_KEY}" # REST path (fallback)
|
|
382
|
+
# mode: "callback" # For async Zapier workflows
|
|
383
|
+
# callback_timeout: 120
|
|
384
|
+
|
|
385
|
+
composio_agent:
|
|
386
|
+
agent_type: "programmatic"
|
|
387
|
+
integration: "composio"
|
|
388
|
+
connector_config:
|
|
389
|
+
action: "GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER"
|
|
390
|
+
# api_key: "${COMPOSIO_API_KEY}"
|
|
391
|
+
# entity_id: "default"
|
|
392
|
+
|
|
393
|
+
n8n_agent:
|
|
394
|
+
agent_type: "programmatic"
|
|
395
|
+
integration: "n8n"
|
|
396
|
+
connector_config:
|
|
397
|
+
webhook_url: "http://localhost:5678/webhook/my-workflow"
|
|
398
|
+
# auth_token: "${N8N_AUTH_TOKEN}"
|
|
399
|
+
# timeout: 60
|
|
400
|
+
# mode: "callback" # For fire-and-forget n8n workflows
|
|
401
|
+
# callback_timeout: 120
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Integration Helpers with @pre_compose
|
|
405
|
+
```python
|
|
406
|
+
from leafmesh import pre_compose, zapier, mcp, composio, n8n
|
|
407
|
+
|
|
408
|
+
@pre_compose(
|
|
409
|
+
context_processor=zapier(action="slack_send", api_key="..."),
|
|
410
|
+
# or: composio(action="GMAIL_SEND", api_key="..."),
|
|
411
|
+
# or: mcp("http://localhost:3000", "search"),
|
|
412
|
+
# or: n8n("http://localhost:5678/webhook/abc"),
|
|
413
|
+
# callback mode: n8n("http://n8n.example.com/webhook/abc", mode="callback", callback_timeout=120),
|
|
414
|
+
)
|
|
415
|
+
async def my_agent(llm_response, input_data, context):
|
|
416
|
+
integration_result = context["prepared_data"]["business_context"]
|
|
417
|
+
return {"result": llm_response, "integration": integration_result}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
All helpers accept `mode="callback"` and `callback_timeout=N` parameters.
|
|
421
|
+
|
|
422
|
+
## Feed Post Structure
|
|
423
|
+
|
|
424
|
+
Each feed post contains:
|
|
425
|
+
|
|
426
|
+
```python
|
|
427
|
+
{
|
|
428
|
+
"post_id": "post:uuid",
|
|
429
|
+
"agent_name": "greeter_agent",
|
|
430
|
+
"session_id": "sess_abc123",
|
|
431
|
+
"timestamp": "2026-03-24T10:00:00",
|
|
432
|
+
"summary": "Processed customer inquiry about pricing",
|
|
433
|
+
"from_agent": "greeter_agent",
|
|
434
|
+
"to_agent": "processor_agent",
|
|
435
|
+
"action_needed": "none", # none | review | escalate
|
|
436
|
+
"priority": "medium", # low | medium | high
|
|
437
|
+
"reason": "Routing to processor",
|
|
438
|
+
"next_agents": ["processor_agent"],
|
|
439
|
+
"workflow_stage": "processing",
|
|
440
|
+
"trigger_event": "mesh.call.completed",
|
|
441
|
+
"work_log": "Received input, analyzed sentiment, produced greeting...",
|
|
442
|
+
"embedding_text": "greeter_agent Processed customer inquiry..."
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## Environment Variables
|
|
447
|
+
|
|
448
|
+
| Variable | Required | Purpose |
|
|
449
|
+
|----------|----------|---------|
|
|
450
|
+
| `LEAFMESH_LICENSE_KEY` | Yes | License key from leafcraft.ai |
|
|
451
|
+
| `LEAFMESH_ENV_TOKEN` | No | Environment token — scopes HITL data + telemetry per environment |
|
|
452
|
+
| `OPENAI_API_KEY` | For OpenAI models | OpenAI API key |
|
|
453
|
+
| `ANTHROPIC_API_KEY` | For Claude models | Anthropic API key |
|
|
454
|
+
| `GOOGLE_API_KEY` | For Gemini models | Google AI API key |
|
|
455
|
+
| `DEEPSEEK_API_KEY` | For DeepSeek models | DeepSeek API key |
|
|
456
|
+
| `AZURE_OPENAI_API_KEY` | For Foundry | Azure OpenAI key |
|
|
457
|
+
| `REDIS_HOST` | No | Redis host (default: localhost) |
|
|
458
|
+
| `REDIS_PORT` | No | Redis port (default: 6379) |
|
|
459
|
+
| `REDIS_PASSWORD` | No | Redis password |
|
|
460
|
+
| `ZAPIER_NLA_API_KEY` | For Zapier | Zapier NLA key |
|
|
461
|
+
| `COMPOSIO_API_KEY` | For Composio | Composio key |
|
|
462
|
+
|
|
463
|
+
## Webhook HMAC Authentication
|
|
464
|
+
|
|
465
|
+
For human agents with webhooks, the SDK auto-derives an HMAC secret from your license key:
|
|
466
|
+
|
|
467
|
+
```python
|
|
468
|
+
from leafmesh import derive_webhook_secret, get_webhook_secret
|
|
469
|
+
|
|
470
|
+
# Derived from LEAFMESH_LICENSE_KEY automatically
|
|
471
|
+
secret = get_webhook_secret()
|
|
472
|
+
# Use for verifying inbound webhook signatures
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
## Error Handling
|
|
476
|
+
|
|
477
|
+
```python
|
|
478
|
+
from leafmesh import LeafMeshError, ConfigError, AgentError, RedisError, LeafMeshLicenseError
|
|
479
|
+
|
|
480
|
+
try:
|
|
481
|
+
result = await sdk.mesh_call("entry", input_data={...})
|
|
482
|
+
except AgentError as e:
|
|
483
|
+
# Agent execution failed
|
|
484
|
+
except RedisError as e:
|
|
485
|
+
# Redis connection/operation failed
|
|
486
|
+
except ConfigError as e:
|
|
487
|
+
# Configuration validation error
|
|
488
|
+
except LeafMeshLicenseError as e:
|
|
489
|
+
# License expired or invalid
|
|
490
|
+
except LeafMeshError as e:
|
|
491
|
+
# Base exception for all SDK errors
|
|
492
|
+
```
|