jarviscore-framework 0.1.1__py3-none-any.whl → 0.2.1__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.
- examples/autoagent_distributed_example.py +211 -0
- examples/custom_profile_decorator.py +134 -0
- examples/custom_profile_wrap.py +168 -0
- examples/customagent_distributed_example.py +362 -0
- examples/customagent_p2p_example.py +730 -0
- jarviscore/__init__.py +49 -36
- jarviscore/adapter/__init__.py +15 -9
- jarviscore/adapter/decorator.py +23 -19
- jarviscore/adapter/wrapper.py +303 -0
- jarviscore/cli/scaffold.py +1 -1
- jarviscore/cli/smoketest.py +3 -2
- jarviscore/core/agent.py +44 -1
- jarviscore/core/mesh.py +196 -35
- jarviscore/data/examples/autoagent_distributed_example.py +211 -0
- jarviscore/data/examples/customagent_distributed_example.py +362 -0
- jarviscore/data/examples/customagent_p2p_example.py +730 -0
- jarviscore/docs/API_REFERENCE.md +264 -51
- jarviscore/docs/AUTOAGENT_GUIDE.md +198 -0
- jarviscore/docs/CONFIGURATION.md +35 -21
- jarviscore/docs/CUSTOMAGENT_GUIDE.md +1362 -0
- jarviscore/docs/GETTING_STARTED.md +107 -14
- jarviscore/docs/TROUBLESHOOTING.md +145 -7
- jarviscore/docs/USER_GUIDE.md +138 -361
- jarviscore/orchestration/engine.py +20 -8
- jarviscore/p2p/__init__.py +10 -0
- jarviscore/p2p/coordinator.py +129 -0
- jarviscore/p2p/messages.py +87 -0
- jarviscore/p2p/peer_client.py +576 -0
- jarviscore/p2p/peer_tool.py +268 -0
- jarviscore_framework-0.2.1.dist-info/METADATA +144 -0
- jarviscore_framework-0.2.1.dist-info/RECORD +132 -0
- {jarviscore_framework-0.1.1.dist-info → jarviscore_framework-0.2.1.dist-info}/WHEEL +1 -1
- {jarviscore_framework-0.1.1.dist-info → jarviscore_framework-0.2.1.dist-info}/top_level.txt +1 -0
- test_logs/code_registry/functions/data_generator-558779ed_560ebc37.py +7 -0
- test_logs/code_registry/functions/data_generator-5ed3609e_560ebc37.py +7 -0
- test_logs/code_registry/functions/data_generator-66da0356_43970bb9.py +25 -0
- test_logs/code_registry/functions/data_generator-7a2fac83_583709d9.py +36 -0
- test_logs/code_registry/functions/data_generator-888b670f_aa235863.py +9 -0
- test_logs/code_registry/functions/data_generator-9ca5f642_aa235863.py +9 -0
- test_logs/code_registry/functions/data_generator-bfd90775_560ebc37.py +7 -0
- test_logs/code_registry/functions/data_generator-e95d2f7d_aa235863.py +9 -0
- test_logs/code_registry/functions/data_generator-f60ca8a2_327eb8c2.py +29 -0
- test_logs/code_registry/functions/mathematician-02adf9ee_958658d9.py +19 -0
- test_logs/code_registry/functions/mathematician-0706fb57_5df13441.py +23 -0
- test_logs/code_registry/functions/mathematician-153c9c4a_ba59c918.py +83 -0
- test_logs/code_registry/functions/mathematician-287e61c0_41daa793.py +18 -0
- test_logs/code_registry/functions/mathematician-2967af5a_863c2cc6.py +17 -0
- test_logs/code_registry/functions/mathematician-303ca6d6_5df13441.py +23 -0
- test_logs/code_registry/functions/mathematician-308a4afd_cbf5064d.py +73 -0
- test_logs/code_registry/functions/mathematician-353f16e2_0968bcf5.py +18 -0
- test_logs/code_registry/functions/mathematician-3c22475a_41daa793.py +17 -0
- test_logs/code_registry/functions/mathematician-5bac1029_0968bcf5.py +18 -0
- test_logs/code_registry/functions/mathematician-640f76b2_9198780b.py +19 -0
- test_logs/code_registry/functions/mathematician-752fa7ea_863c2cc6.py +17 -0
- test_logs/code_registry/functions/mathematician-baf9ef39_0968bcf5.py +18 -0
- test_logs/code_registry/functions/mathematician-bc8b2a2f_5df13441.py +23 -0
- test_logs/code_registry/functions/mathematician-c31e4686_41daa793.py +18 -0
- test_logs/code_registry/functions/mathematician-cc84c84c_863c2cc6.py +17 -0
- test_logs/code_registry/functions/mathematician-dd7c7144_9198780b.py +19 -0
- test_logs/code_registry/functions/mathematician-e671c256_41ea4487.py +74 -0
- test_logs/code_registry/functions/report_generator-1a878fcc_18d44bdc.py +47 -0
- test_logs/code_registry/functions/report_generator-25c1c331_cea57d0d.py +35 -0
- test_logs/code_registry/functions/report_generator-37552117_e711c2b9.py +35 -0
- test_logs/code_registry/functions/report_generator-bc662768_e711c2b9.py +35 -0
- test_logs/code_registry/functions/report_generator-d6c0e76b_5e7722ec.py +44 -0
- test_logs/code_registry/functions/report_generator-f270fb02_680529c3.py +44 -0
- test_logs/code_registry/functions/text_processor-11393b14_4370d3ed.py +40 -0
- test_logs/code_registry/functions/text_processor-7d02dfc3_d3b569be.py +37 -0
- test_logs/code_registry/functions/text_processor-8adb5e32_9168c5fe.py +13 -0
- test_logs/code_registry/functions/text_processor-c58ffc19_78b4ceac.py +42 -0
- test_logs/code_registry/functions/text_processor-cd5977b1_9168c5fe.py +13 -0
- test_logs/code_registry/functions/text_processor-ec1c8773_9168c5fe.py +13 -0
- tests/test_01_analyst_standalone.py +124 -0
- tests/test_02_assistant_standalone.py +164 -0
- tests/test_03_analyst_with_framework.py +945 -0
- tests/test_04_assistant_with_framework.py +1002 -0
- tests/test_05_integration.py +1301 -0
- tests/test_06_real_llm_integration.py +760 -0
- tests/test_07_distributed_single_node.py +578 -0
- tests/test_08_distributed_multi_node.py +454 -0
- tests/test_09_distributed_autoagent.py +509 -0
- tests/test_10_distributed_customagent.py +787 -0
- tests/test_mesh.py +35 -4
- jarviscore_framework-0.1.1.dist-info/METADATA +0 -137
- jarviscore_framework-0.1.1.dist-info/RECORD +0 -69
- {jarviscore_framework-0.1.1.dist-info → jarviscore_framework-0.2.1.dist-info}/licenses/LICENSE +0 -0
jarviscore/docs/API_REFERENCE.md
CHANGED
|
@@ -12,6 +12,7 @@ Complete API documentation for JarvisCore framework components.
|
|
|
12
12
|
- [Profile](#profile)
|
|
13
13
|
2. [Agent Profiles](#agent-profiles)
|
|
14
14
|
- [AutoAgent](#autoagent)
|
|
15
|
+
- [Custom Profile](#custom-profile)
|
|
15
16
|
- [CustomAgent](#customagent)
|
|
16
17
|
3. [Execution Components](#execution-components)
|
|
17
18
|
- [CodeGenerator](#codegenerator)
|
|
@@ -39,35 +40,43 @@ The central orchestrator for managing agents and workflows.
|
|
|
39
40
|
```python
|
|
40
41
|
from jarviscore import Mesh
|
|
41
42
|
|
|
42
|
-
mesh = Mesh(mode="autonomous") # or "distributed"
|
|
43
|
+
mesh = Mesh(mode="autonomous") # or "p2p" or "distributed"
|
|
43
44
|
```
|
|
44
45
|
|
|
45
46
|
**Parameters:**
|
|
46
|
-
- `mode` (str): Execution mode
|
|
47
|
+
- `mode` (str): Execution mode
|
|
48
|
+
- `"autonomous"` - Workflow Engine only (single-node)
|
|
49
|
+
- `"p2p"` - P2P Coordinator only (SWIM protocol, ZMQ messaging)
|
|
50
|
+
- `"distributed"` - Both Workflow Engine AND P2P Coordinator
|
|
47
51
|
- `config` (dict, optional): Configuration dictionary
|
|
48
52
|
|
|
53
|
+
**Modes Comparison:**
|
|
54
|
+
|
|
55
|
+
| Mode | Workflow Engine | P2P Coordinator | Use Case |
|
|
56
|
+
|------|-----------------|-----------------|----------|
|
|
57
|
+
| `autonomous` | ✅ | ❌ | Single machine, simple pipelines |
|
|
58
|
+
| `p2p` | ❌ | ✅ | Agent swarms, real-time coordination |
|
|
59
|
+
| `distributed` | ✅ | ✅ | Multi-node production systems |
|
|
60
|
+
|
|
49
61
|
**Methods:**
|
|
50
62
|
|
|
51
|
-
#### `
|
|
63
|
+
#### `add(agent_class)`
|
|
52
64
|
|
|
53
|
-
Register an agent in the mesh.
|
|
65
|
+
Register an agent class in the mesh.
|
|
54
66
|
|
|
55
67
|
```python
|
|
56
68
|
from jarviscore.profiles import AutoAgent
|
|
57
69
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
)
|
|
70
|
+
class CalculatorAgent(AutoAgent):
|
|
71
|
+
role = "calculator"
|
|
72
|
+
capabilities = ["math", "calculation"]
|
|
73
|
+
system_prompt = "You are a math expert"
|
|
74
|
+
|
|
75
|
+
mesh.add(CalculatorAgent)
|
|
64
76
|
```
|
|
65
77
|
|
|
66
78
|
**Parameters:**
|
|
67
|
-
- `
|
|
68
|
-
- `role` (str): Unique agent role identifier
|
|
69
|
-
- `capabilities` (list): List of capability strings
|
|
70
|
-
- `**kwargs`: Additional agent-specific parameters
|
|
79
|
+
- `agent_class`: Agent class (AutoAgent or CustomAgent subclass)
|
|
71
80
|
|
|
72
81
|
**Returns:** Agent instance
|
|
73
82
|
|
|
@@ -95,12 +104,12 @@ await mesh.stop()
|
|
|
95
104
|
|
|
96
105
|
---
|
|
97
106
|
|
|
98
|
-
#### `async
|
|
107
|
+
#### `async workflow(workflow_id, steps)`
|
|
99
108
|
|
|
100
109
|
Execute a multi-step workflow with dependency management.
|
|
101
110
|
|
|
102
111
|
```python
|
|
103
|
-
results = await mesh.
|
|
112
|
+
results = await mesh.workflow("pipeline-id", [
|
|
104
113
|
{"agent": "scraper", "task": "Scrape data from URL"},
|
|
105
114
|
{"agent": "processor", "task": "Clean the data", "depends_on": [0]},
|
|
106
115
|
{"agent": "storage", "task": "Save to database", "depends_on": [1]}
|
|
@@ -108,6 +117,7 @@ results = await mesh.run_workflow([
|
|
|
108
117
|
```
|
|
109
118
|
|
|
110
119
|
**Parameters:**
|
|
120
|
+
- `workflow_id` (str): Unique workflow identifier
|
|
111
121
|
- `steps` (list): List of step dictionaries with keys:
|
|
112
122
|
- `agent` (str): Role or capability of target agent
|
|
113
123
|
- `task` (str): Task description
|
|
@@ -116,6 +126,20 @@ results = await mesh.run_workflow([
|
|
|
116
126
|
|
|
117
127
|
**Returns:** List of result dictionaries
|
|
118
128
|
|
|
129
|
+
**Note:** Only available in `autonomous` and `distributed` modes.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
#### `async run_forever()`
|
|
134
|
+
|
|
135
|
+
Keep the mesh running until shutdown signal (P2P and distributed modes).
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
await mesh.run_forever() # Blocks until SIGINT/SIGTERM
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Note:** Only available in `p2p` and `distributed` modes.
|
|
142
|
+
|
|
119
143
|
---
|
|
120
144
|
|
|
121
145
|
### Agent
|
|
@@ -288,6 +312,180 @@ results = await mesh.run_workflow([
|
|
|
288
312
|
|
|
289
313
|
---
|
|
290
314
|
|
|
315
|
+
### Custom Profile
|
|
316
|
+
|
|
317
|
+
The Custom Profile enables integration of existing agents without modification.
|
|
318
|
+
|
|
319
|
+
#### Decorator: `@jarvis_agent`
|
|
320
|
+
|
|
321
|
+
Convert any Python class into a JarvisCore agent:
|
|
322
|
+
|
|
323
|
+
```python
|
|
324
|
+
from jarviscore import jarvis_agent, JarvisContext
|
|
325
|
+
|
|
326
|
+
@jarvis_agent(role="processor", capabilities=["data_processing"])
|
|
327
|
+
class DataProcessor:
|
|
328
|
+
def run(self, data):
|
|
329
|
+
return {"processed": [x * 2 for x in data]}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**Parameters:**
|
|
333
|
+
- `role` (str): Agent role identifier
|
|
334
|
+
- `capabilities` (list): List of capability strings
|
|
335
|
+
- `execute_method` (str, optional): Method name to call (default: auto-detect)
|
|
336
|
+
|
|
337
|
+
**Auto-detected Methods:** `run`, `execute`, `invoke`, `call`, `process`
|
|
338
|
+
|
|
339
|
+
**Context-Aware Methods:**
|
|
340
|
+
|
|
341
|
+
If your method has a parameter named `ctx` or `context`, JarvisContext is automatically injected:
|
|
342
|
+
|
|
343
|
+
```python
|
|
344
|
+
@jarvis_agent(role="aggregator", capabilities=["aggregation"])
|
|
345
|
+
class Aggregator:
|
|
346
|
+
def run(self, task, ctx: JarvisContext):
|
|
347
|
+
previous = ctx.previous("step1")
|
|
348
|
+
return {"result": previous}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
#### Function: `wrap()`
|
|
354
|
+
|
|
355
|
+
Wrap an existing instance as a JarvisCore agent:
|
|
356
|
+
|
|
357
|
+
```python
|
|
358
|
+
from jarviscore import wrap
|
|
359
|
+
|
|
360
|
+
wrapped = wrap(
|
|
361
|
+
instance=my_langchain_agent,
|
|
362
|
+
role="assistant",
|
|
363
|
+
capabilities=["chat", "qa"],
|
|
364
|
+
execute_method="invoke"
|
|
365
|
+
)
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**Parameters:**
|
|
369
|
+
- `instance` (Any): Pre-instantiated object to wrap
|
|
370
|
+
- `role` (str): Agent role identifier
|
|
371
|
+
- `capabilities` (list): List of capability strings
|
|
372
|
+
- `execute_method` (str, optional): Method name to call (default: auto-detect)
|
|
373
|
+
|
|
374
|
+
**Returns:** `CustomAgent` instance ready for `mesh.add()`
|
|
375
|
+
|
|
376
|
+
**Example:**
|
|
377
|
+
|
|
378
|
+
```python
|
|
379
|
+
from jarviscore import Mesh, wrap
|
|
380
|
+
|
|
381
|
+
# Your existing LangChain agent
|
|
382
|
+
my_agent = MyLangChainAgent(model="gpt-4")
|
|
383
|
+
|
|
384
|
+
# Wrap it
|
|
385
|
+
wrapped = wrap(
|
|
386
|
+
my_agent,
|
|
387
|
+
role="assistant",
|
|
388
|
+
capabilities=["chat"],
|
|
389
|
+
execute_method="invoke"
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
mesh = Mesh(mode="autonomous")
|
|
393
|
+
mesh.add(wrapped) # Add directly to mesh
|
|
394
|
+
await mesh.start()
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
#### Class: `JarvisContext`
|
|
400
|
+
|
|
401
|
+
Provides workflow context access for Custom Profile agents:
|
|
402
|
+
|
|
403
|
+
```python
|
|
404
|
+
from jarviscore import JarvisContext
|
|
405
|
+
|
|
406
|
+
def run(self, task, ctx: JarvisContext):
|
|
407
|
+
# Access previous step outputs
|
|
408
|
+
step1_output = ctx.previous("step1")
|
|
409
|
+
|
|
410
|
+
# Get all previous outputs
|
|
411
|
+
all_outputs = ctx.all_previous()
|
|
412
|
+
|
|
413
|
+
# Access shared memory
|
|
414
|
+
ctx.memory["key"] = "value"
|
|
415
|
+
value = ctx.memory.get("key")
|
|
416
|
+
|
|
417
|
+
return {"result": "..."}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**Attributes:**
|
|
421
|
+
- `workflow_id` (str): Current workflow identifier
|
|
422
|
+
- `step_id` (str): Current step identifier
|
|
423
|
+
- `task` (str): Task description
|
|
424
|
+
- `params` (dict): Task parameters
|
|
425
|
+
- `memory` (MemoryAccessor): Shared workflow memory
|
|
426
|
+
|
|
427
|
+
**Methods:**
|
|
428
|
+
|
|
429
|
+
#### `previous(step_id: str) -> Optional[Any]`
|
|
430
|
+
|
|
431
|
+
Get output from a specific previous step.
|
|
432
|
+
|
|
433
|
+
```python
|
|
434
|
+
step1_output = ctx.previous("step1")
|
|
435
|
+
if step1_output:
|
|
436
|
+
data = step1_output.get("processed", [])
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
**Parameters:**
|
|
440
|
+
- `step_id` (str): ID of the step to retrieve
|
|
441
|
+
|
|
442
|
+
**Returns:** Step output or None if not found
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
#### `all_previous() -> Dict[str, Any]`
|
|
447
|
+
|
|
448
|
+
Get outputs from all previous steps.
|
|
449
|
+
|
|
450
|
+
```python
|
|
451
|
+
all_outputs = ctx.all_previous()
|
|
452
|
+
# {"step1": {...}, "step2": {...}}
|
|
453
|
+
|
|
454
|
+
for step_id, output in all_outputs.items():
|
|
455
|
+
print(f"{step_id}: {output}")
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
**Returns:** Dictionary mapping step IDs to their outputs
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
#### Class: `MemoryAccessor`
|
|
463
|
+
|
|
464
|
+
Dictionary-like interface for shared workflow memory:
|
|
465
|
+
|
|
466
|
+
```python
|
|
467
|
+
# Set value
|
|
468
|
+
ctx.memory["key"] = "value"
|
|
469
|
+
|
|
470
|
+
# Get value
|
|
471
|
+
value = ctx.memory.get("key", "default")
|
|
472
|
+
|
|
473
|
+
# Check existence
|
|
474
|
+
if "key" in ctx.memory:
|
|
475
|
+
...
|
|
476
|
+
|
|
477
|
+
# Get all memory
|
|
478
|
+
all_memory = ctx.memory.all()
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
**Methods:**
|
|
482
|
+
- `get(key, default=None)` - Get value with optional default
|
|
483
|
+
- `set(key, value)` - Set value
|
|
484
|
+
- `all()` - Get entire memory dictionary
|
|
485
|
+
- `__getitem__`, `__setitem__`, `__contains__` - Dict-like access
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
291
489
|
### CustomAgent
|
|
292
490
|
|
|
293
491
|
Flexible agent profile for integrating external frameworks.
|
|
@@ -297,51 +495,66 @@ Flexible agent profile for integrating external frameworks.
|
|
|
297
495
|
```python
|
|
298
496
|
from jarviscore.profiles import CustomAgent
|
|
299
497
|
|
|
300
|
-
class
|
|
498
|
+
class MyAgent(CustomAgent):
|
|
499
|
+
role = "my_role"
|
|
500
|
+
capabilities = ["my_capability"]
|
|
501
|
+
|
|
301
502
|
async def setup(self):
|
|
302
|
-
|
|
303
|
-
|
|
503
|
+
await super().setup()
|
|
504
|
+
# Initialize your resources
|
|
304
505
|
|
|
305
506
|
async def execute_task(self, task):
|
|
306
|
-
|
|
307
|
-
return {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
507
|
+
"""Called by workflow engine (autonomous/distributed modes)."""
|
|
508
|
+
return {"status": "success", "output": result}
|
|
509
|
+
|
|
510
|
+
async def run(self):
|
|
511
|
+
"""Called in P2P mode - continuous run loop."""
|
|
512
|
+
while not self.shutdown_requested:
|
|
513
|
+
msg = await self.peers.receive(timeout=0.5)
|
|
514
|
+
if msg and msg.is_request:
|
|
515
|
+
await self.peers.respond(msg, {"response": "..."})
|
|
312
516
|
```
|
|
313
517
|
|
|
314
|
-
**
|
|
315
|
-
-
|
|
316
|
-
-
|
|
317
|
-
- Optional cost tracking with `track_cost()`
|
|
318
|
-
- Full access to mesh and workflow context
|
|
518
|
+
**Class Attributes:**
|
|
519
|
+
- `role` (str): Agent role identifier (required)
|
|
520
|
+
- `capabilities` (list): List of capability strings (required)
|
|
319
521
|
|
|
320
|
-
**
|
|
522
|
+
**Instance Attributes:**
|
|
523
|
+
- `agent_id` (str): Unique agent identifier
|
|
524
|
+
- `peers` (PeerTool): P2P communication tool (distributed/p2p modes)
|
|
525
|
+
- `shutdown_requested` (bool): Set to True when shutdown requested
|
|
321
526
|
|
|
322
|
-
|
|
323
|
-
class APIAgent(CustomAgent):
|
|
324
|
-
async def setup(self):
|
|
325
|
-
self.api_client = MyAPIClient()
|
|
527
|
+
**Key Methods:**
|
|
326
528
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
529
|
+
| Method | Purpose | Mode |
|
|
530
|
+
|--------|---------|------|
|
|
531
|
+
| `setup()` | Initialize resources | All |
|
|
532
|
+
| `execute_task(task)` | Handle workflow steps | Autonomous/Distributed |
|
|
533
|
+
| `run()` | Continuous loop | P2P |
|
|
534
|
+
| `teardown()` | Cleanup resources | All |
|
|
330
535
|
|
|
331
|
-
|
|
332
|
-
self.track_cost(
|
|
333
|
-
input_tokens=100,
|
|
334
|
-
output_tokens=50,
|
|
335
|
-
cost_usd=0.01
|
|
336
|
-
)
|
|
536
|
+
**P2P Communication (distributed/p2p modes):**
|
|
337
537
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
538
|
+
```python
|
|
539
|
+
async def run(self):
|
|
540
|
+
while not self.shutdown_requested:
|
|
541
|
+
# Receive messages
|
|
542
|
+
msg = await self.peers.receive(timeout=0.5)
|
|
543
|
+
if msg and msg.is_request:
|
|
544
|
+
# Process and respond
|
|
545
|
+
await self.peers.respond(msg, {"response": result})
|
|
546
|
+
|
|
547
|
+
async def ask_another_agent(self, question):
|
|
548
|
+
# Ask another agent via peer tools
|
|
549
|
+
result = await self.peers.as_tool().execute(
|
|
550
|
+
"ask_peer",
|
|
551
|
+
{"role": "researcher", "question": question}
|
|
552
|
+
)
|
|
553
|
+
return result
|
|
343
554
|
```
|
|
344
555
|
|
|
556
|
+
See [CustomAgent Guide](CUSTOMAGENT_GUIDE.md) for P2P and distributed mode details.
|
|
557
|
+
|
|
345
558
|
---
|
|
346
559
|
|
|
347
560
|
## Execution Components
|
|
@@ -927,6 +1140,6 @@ async def execute_task(self, task: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
927
1140
|
|
|
928
1141
|
## Version
|
|
929
1142
|
|
|
930
|
-
API Reference for JarvisCore v0.1
|
|
1143
|
+
API Reference for JarvisCore v0.2.1
|
|
931
1144
|
|
|
932
|
-
Last Updated: 2026-01-
|
|
1145
|
+
Last Updated: 2026-01-23
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# AutoAgent Guide
|
|
2
|
+
|
|
3
|
+
AutoAgent is the **zero-config** profile where the framework handles everything:
|
|
4
|
+
- LLM code generation from natural language
|
|
5
|
+
- Sandboxed code execution
|
|
6
|
+
- Automatic error repair
|
|
7
|
+
- Result storage
|
|
8
|
+
|
|
9
|
+
You write **3 attributes**, framework does the rest.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Quick Reference
|
|
14
|
+
|
|
15
|
+
| Mode | Use Case | Key Difference |
|
|
16
|
+
|------|----------|----------------|
|
|
17
|
+
| **Autonomous** | Single machine | No network, local execution |
|
|
18
|
+
| **Distributed** | Multi-node | P2P network + workflow orchestration |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Autonomous Mode
|
|
23
|
+
|
|
24
|
+
Single-node execution. No networking required.
|
|
25
|
+
|
|
26
|
+
### Example
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
import asyncio
|
|
30
|
+
from jarviscore import Mesh
|
|
31
|
+
from jarviscore.profiles import AutoAgent
|
|
32
|
+
|
|
33
|
+
class CalculatorAgent(AutoAgent):
|
|
34
|
+
role = "calculator"
|
|
35
|
+
capabilities = ["math", "calculation"]
|
|
36
|
+
system_prompt = """
|
|
37
|
+
You are a math expert. Generate Python code to solve problems.
|
|
38
|
+
Store the result in a variable named 'result'.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
async def main():
|
|
42
|
+
mesh = Mesh(mode="autonomous") # Default mode
|
|
43
|
+
mesh.add(CalculatorAgent)
|
|
44
|
+
|
|
45
|
+
await mesh.start()
|
|
46
|
+
|
|
47
|
+
results = await mesh.workflow("calc-task", [
|
|
48
|
+
{"agent": "calculator", "task": "Calculate factorial of 10"}
|
|
49
|
+
])
|
|
50
|
+
|
|
51
|
+
print(results[0]["output"]) # {'result': 3628800}
|
|
52
|
+
|
|
53
|
+
await mesh.stop()
|
|
54
|
+
|
|
55
|
+
asyncio.run(main())
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### When to Use
|
|
59
|
+
- Rapid prototyping
|
|
60
|
+
- Single-machine deployments
|
|
61
|
+
- Simple task pipelines
|
|
62
|
+
- No need for agent-to-agent communication
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Distributed Mode
|
|
67
|
+
|
|
68
|
+
Multi-node execution with P2P networking. Same API, just add config.
|
|
69
|
+
|
|
70
|
+
### What Changes
|
|
71
|
+
|
|
72
|
+
| Autonomous | Distributed |
|
|
73
|
+
|------------|-------------|
|
|
74
|
+
| `mode="autonomous"` | `mode="distributed"` |
|
|
75
|
+
| No config needed | Add `bind_port`, `node_name` |
|
|
76
|
+
| Single machine | Can span multiple machines |
|
|
77
|
+
|
|
78
|
+
### Example (Single Node)
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
import asyncio
|
|
82
|
+
from jarviscore import Mesh
|
|
83
|
+
from jarviscore.profiles import AutoAgent
|
|
84
|
+
|
|
85
|
+
class CalculatorAgent(AutoAgent):
|
|
86
|
+
role = "calculator"
|
|
87
|
+
capabilities = ["math", "calculation"]
|
|
88
|
+
system_prompt = """
|
|
89
|
+
You are a math expert. Generate Python code to solve problems.
|
|
90
|
+
Store the result in a variable named 'result'.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
async def main():
|
|
94
|
+
mesh = Mesh(
|
|
95
|
+
mode="distributed", # Enable P2P + workflow
|
|
96
|
+
config={
|
|
97
|
+
'bind_port': 7950, # SWIM protocol port
|
|
98
|
+
'node_name': 'calc-node', # Node identifier
|
|
99
|
+
}
|
|
100
|
+
)
|
|
101
|
+
mesh.add(CalculatorAgent)
|
|
102
|
+
|
|
103
|
+
await mesh.start()
|
|
104
|
+
|
|
105
|
+
# Same API as autonomous!
|
|
106
|
+
results = await mesh.workflow("calc-task", [
|
|
107
|
+
{"agent": "calculator", "task": "Calculate factorial of 10"}
|
|
108
|
+
])
|
|
109
|
+
|
|
110
|
+
print(results[0]["output"])
|
|
111
|
+
|
|
112
|
+
await mesh.stop()
|
|
113
|
+
|
|
114
|
+
asyncio.run(main())
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Example (Multi-Node)
|
|
118
|
+
|
|
119
|
+
**Node 1 - Seed node with calculator:**
|
|
120
|
+
```python
|
|
121
|
+
# node1.py
|
|
122
|
+
mesh = Mesh(
|
|
123
|
+
mode="distributed",
|
|
124
|
+
config={
|
|
125
|
+
'bind_host': '0.0.0.0',
|
|
126
|
+
'bind_port': 7950,
|
|
127
|
+
'node_name': 'node-1',
|
|
128
|
+
}
|
|
129
|
+
)
|
|
130
|
+
mesh.add(CalculatorAgent)
|
|
131
|
+
await mesh.start()
|
|
132
|
+
await mesh.serve_forever() # Keep running
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Node 2 - Joins cluster with analyzer:**
|
|
136
|
+
```python
|
|
137
|
+
# node2.py
|
|
138
|
+
mesh = Mesh(
|
|
139
|
+
mode="distributed",
|
|
140
|
+
config={
|
|
141
|
+
'bind_host': '0.0.0.0',
|
|
142
|
+
'bind_port': 7950,
|
|
143
|
+
'node_name': 'node-2',
|
|
144
|
+
'seed_nodes': '192.168.1.10:7950', # Node 1's address
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
mesh.add(AnalyzerAgent)
|
|
148
|
+
await mesh.start()
|
|
149
|
+
await mesh.serve_forever()
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Execute workflows across nodes:**
|
|
153
|
+
```python
|
|
154
|
+
# From any node
|
|
155
|
+
results = await mesh.workflow("cross-node", [
|
|
156
|
+
{"agent": "calculator", "task": "..."}, # Runs on Node 1
|
|
157
|
+
{"agent": "analyzer", "task": "...", "depends_on": [0]} # Runs on Node 2
|
|
158
|
+
])
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### When to Use
|
|
162
|
+
- Production multi-node systems
|
|
163
|
+
- Agents on different machines
|
|
164
|
+
- Scalable agent architectures
|
|
165
|
+
- Need cross-node workflow coordination
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Configuration Options
|
|
170
|
+
|
|
171
|
+
| Option | Default | Description |
|
|
172
|
+
|--------|---------|-------------|
|
|
173
|
+
| `bind_host` | `127.0.0.1` | Interface to bind |
|
|
174
|
+
| `bind_port` | `7950` | SWIM protocol port |
|
|
175
|
+
| `node_name` | `jarviscore-node` | Node identifier |
|
|
176
|
+
| `seed_nodes` | `None` | Comma-separated seed addresses |
|
|
177
|
+
| `execution_timeout` | `300` | Max seconds per task |
|
|
178
|
+
| `max_repair_attempts` | `3` | Auto-repair retries |
|
|
179
|
+
| `log_directory` | `./logs` | Result storage path |
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Summary
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
# Autonomous (single node)
|
|
187
|
+
mesh = Mesh(mode="autonomous")
|
|
188
|
+
|
|
189
|
+
# Distributed (multi-node capable)
|
|
190
|
+
mesh = Mesh(mode="distributed", config={'bind_port': 7950})
|
|
191
|
+
|
|
192
|
+
# Everything else stays the same!
|
|
193
|
+
mesh.add(MyAutoAgent)
|
|
194
|
+
await mesh.start()
|
|
195
|
+
results = await mesh.workflow(...)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
See `examples/calculator_agent_example.py` and `examples/autoagent_distributed_example.py` for complete examples.
|
jarviscore/docs/CONFIGURATION.md
CHANGED
|
@@ -251,27 +251,28 @@ Generated code is automatically registered:
|
|
|
251
251
|
|
|
252
252
|
## P2P Configuration
|
|
253
253
|
|
|
254
|
-
Configure distributed mesh networking
|
|
254
|
+
Configure distributed mesh networking for `p2p` and `distributed` modes.
|
|
255
255
|
|
|
256
|
-
###
|
|
256
|
+
### Execution Modes
|
|
257
257
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
NODE_NAME=jarviscore-node-1
|
|
264
|
-
```
|
|
258
|
+
| Mode | Code Config | Workflow Engine | P2P Coordinator |
|
|
259
|
+
|------|-------------|-----------------|-----------------|
|
|
260
|
+
| `autonomous` | `Mesh(mode="autonomous")` | ✅ | ❌ |
|
|
261
|
+
| `p2p` | `Mesh(mode="p2p", config={...})` | ❌ | ✅ |
|
|
262
|
+
| `distributed` | `Mesh(mode="distributed", config={...})` | ✅ | ✅ |
|
|
265
263
|
|
|
266
|
-
### Network Settings
|
|
264
|
+
### Network Settings (P2P and Distributed)
|
|
267
265
|
|
|
268
266
|
```bash
|
|
269
267
|
# Bind address and port
|
|
270
268
|
BIND_HOST=0.0.0.0 # Listen on all interfaces
|
|
271
|
-
BIND_PORT=
|
|
269
|
+
BIND_PORT=7950 # SWIM protocol port
|
|
272
270
|
|
|
273
|
-
#
|
|
274
|
-
|
|
271
|
+
# Node identification
|
|
272
|
+
NODE_NAME=jarviscore-node-1
|
|
273
|
+
|
|
274
|
+
# Seed nodes (comma-separated) for joining existing cluster
|
|
275
|
+
SEED_NODES=192.168.1.100:7950,192.168.1.101:7950
|
|
275
276
|
```
|
|
276
277
|
|
|
277
278
|
### Transport Configuration
|
|
@@ -540,14 +541,27 @@ Override environment variables in code:
|
|
|
540
541
|
```python
|
|
541
542
|
from jarviscore import Mesh
|
|
542
543
|
|
|
543
|
-
config
|
|
544
|
-
|
|
545
|
-
'sandbox_service_url': 'https://...',
|
|
544
|
+
# Autonomous mode (no P2P config needed)
|
|
545
|
+
mesh = Mesh(mode="autonomous", config={
|
|
546
546
|
'execution_timeout': 600,
|
|
547
547
|
'log_level': 'DEBUG'
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
|
|
548
|
+
})
|
|
549
|
+
|
|
550
|
+
# P2P mode (requires network config)
|
|
551
|
+
mesh = Mesh(mode="p2p", config={
|
|
552
|
+
'bind_host': '0.0.0.0',
|
|
553
|
+
'bind_port': 7950,
|
|
554
|
+
'node_name': 'my-node',
|
|
555
|
+
'seed_nodes': '192.168.1.10:7950', # Optional, for joining cluster
|
|
556
|
+
})
|
|
557
|
+
|
|
558
|
+
# Distributed mode (both workflow + P2P)
|
|
559
|
+
mesh = Mesh(mode="distributed", config={
|
|
560
|
+
'bind_host': '0.0.0.0',
|
|
561
|
+
'bind_port': 7950,
|
|
562
|
+
'node_name': 'my-node',
|
|
563
|
+
'execution_timeout': 600,
|
|
564
|
+
})
|
|
551
565
|
```
|
|
552
566
|
|
|
553
567
|
**Note:** Programmatic config overrides environment variables.
|
|
@@ -752,6 +766,6 @@ LOG_DIRECTORY=/tmp/jarviscore-logs
|
|
|
752
766
|
|
|
753
767
|
## Version
|
|
754
768
|
|
|
755
|
-
Configuration Guide for JarvisCore v0.1
|
|
769
|
+
Configuration Guide for JarvisCore v0.2.1
|
|
756
770
|
|
|
757
|
-
Last Updated: 2026-01-
|
|
771
|
+
Last Updated: 2026-01-23
|