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.
Files changed (31) hide show
  1. create_leafmesh/__init__.py +3 -0
  2. create_leafmesh/cli.py +252 -0
  3. create_leafmesh/create.py +106 -0
  4. create_leafmesh/templates/Dockerfile +21 -0
  5. create_leafmesh/templates/README.md +309 -0
  6. create_leafmesh/templates/agency/__init__.py +0 -0
  7. create_leafmesh/templates/agency/advisor_agent.py +151 -0
  8. create_leafmesh/templates/agency/external_agents.py +278 -0
  9. create_leafmesh/templates/agency/fallback_researcher_agent.py +80 -0
  10. create_leafmesh/templates/agency/greeter_agent.py +79 -0
  11. create_leafmesh/templates/agency/processor_agent.py +90 -0
  12. create_leafmesh/templates/agency/researcher_agent.py +99 -0
  13. create_leafmesh/templates/agency/scheduler_agent.py +67 -0
  14. create_leafmesh/templates/agency/tools.py +123 -0
  15. create_leafmesh/templates/claude_skills/leafmesh/SKILL.md +2049 -0
  16. create_leafmesh/templates/claude_skills/leafmesh/agent-config-fields.md +1309 -0
  17. create_leafmesh/templates/claude_skills/leafmesh/examples.md +537 -0
  18. create_leafmesh/templates/claude_skills/leafmesh/reference.md +492 -0
  19. create_leafmesh/templates/configs/config.yaml +1028 -0
  20. create_leafmesh/templates/docker-compose.yml +28 -0
  21. create_leafmesh/templates/dockerignore +17 -0
  22. create_leafmesh/templates/env +109 -0
  23. create_leafmesh/templates/gitignore +33 -0
  24. create_leafmesh/templates/hitl_stub_receiver.py +149 -0
  25. create_leafmesh/templates/main.py +105 -0
  26. create_leafmesh/templates/requirements.txt +10 -0
  27. create_leafmesh-2.1.0.dist-info/METADATA +6 -0
  28. create_leafmesh-2.1.0.dist-info/RECORD +31 -0
  29. create_leafmesh-2.1.0.dist-info/WHEEL +5 -0
  30. create_leafmesh-2.1.0.dist-info/entry_points.txt +2 -0
  31. 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
+ ```