jaf-py 2.2.3__tar.gz → 2.3.0__tar.gz
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.
- {jaf_py-2.2.3 → jaf_py-2.3.0}/PKG-INFO +143 -5
- {jaf_py-2.2.3 → jaf_py-2.3.0}/README.md +142 -4
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/engine.py +10 -2
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/tracing.py +187 -37
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/types.py +5 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/providers/model.py +5 -2
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf_py.egg-info/PKG-INFO +143 -5
- {jaf_py-2.2.3 → jaf_py-2.3.0}/pyproject.toml +1 -1
- {jaf_py-2.2.3 → jaf_py-2.3.0}/LICENSE +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/agent.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/agent_card.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/client.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/examples/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/examples/client_example.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/examples/integration_example.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/examples/rag_demo/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/examples/server_demo/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/examples/server_example.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/cleanup.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/factory.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/providers/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/providers/composite.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/providers/in_memory.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/providers/postgres.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/providers/redis.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/serialization.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/tests/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/tests/run_comprehensive_tests.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/tests/test_cleanup.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/tests/test_serialization.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/tests/test_stress_concurrency.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/tests/test_task_lifecycle.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/types.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/protocol.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/server.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/standalone_client.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/run_tests.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/test_agent.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/test_client.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/test_integration.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/test_protocol.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/test_types.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/types.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/cli.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/agent_tool.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/analytics.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/composition.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/errors.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/performance.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/proxy.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/proxy_helpers.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/streaming.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/tool_results.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/tools.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/workflows.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/exceptions.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/factory.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/providers/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/providers/in_memory.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/providers/postgres.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/providers/redis.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/types.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/utils.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/plugins/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/plugins/base.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/policies/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/policies/handoff.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/policies/validation.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/providers/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/providers/mcp.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/server/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/server/main.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/server/server.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/server/types.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/visualization/__init__.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/visualization/example.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/visualization/functional_core.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/visualization/graphviz.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/visualization/imperative_shell.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/visualization/types.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf_py.egg-info/SOURCES.txt +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf_py.egg-info/dependency_links.txt +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf_py.egg-info/entry_points.txt +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf_py.egg-info/requires.txt +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf_py.egg-info/top_level.txt +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/setup.cfg +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/setup.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_a2a_deep.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_a2a_examples.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_api_reference_examples.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_callback_system_examples.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_coffee_tool.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_conversation_id_fix.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_deployment_examples.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_docs_code_examples.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_engine.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_engine_manual.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_error_handling_examples.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_getting_started_examples.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_math_tool.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_mcp_comprehensive.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_mcp_docs.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_mcp_real_functionality.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_mcp_transports.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_memory_system_examples.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_model_providers_examples.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_property_based.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_proxy_simple.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_redis_fixes.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_redis_memory.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_server_api_examples.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_session_continuity.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_streamable_http_mcp_example.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_timeout_functionality.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_tool_integration.py +0 -0
- {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_validation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jaf-py
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: A purely functional agent framework with immutable state and composable tools - Python implementation
|
|
5
5
|
Author: JAF Contributors
|
|
6
6
|
Maintainer: JAF Contributors
|
|
@@ -73,7 +73,7 @@ Dynamic: license-file
|
|
|
73
73
|
|
|
74
74
|
<!--  -->
|
|
75
75
|
|
|
76
|
-
[](https://github.com/xynehq/jaf-py)
|
|
77
77
|
[](https://www.python.org/)
|
|
78
78
|
[](https://xynehq.github.io/jaf-py/)
|
|
79
79
|
|
|
@@ -114,15 +114,23 @@ A purely functional agent framework with immutable state and composable tools, p
|
|
|
114
114
|
|
|
115
115
|
### 📊 **Observability & Monitoring**
|
|
116
116
|
- ✅ **Real-time Tracing**: Event-driven observability
|
|
117
|
+
- ✅ **OpenTelemetry Integration**: Distributed tracing with OTLP
|
|
118
|
+
- ✅ **Langfuse Tracing**: LLM observability and analytics
|
|
117
119
|
- ✅ **Structured Logging**: JSON-formatted logs
|
|
118
120
|
- ✅ **Error Handling**: Comprehensive error types and recovery
|
|
119
121
|
- ✅ **Performance Metrics**: Built-in timing and counters
|
|
120
122
|
|
|
123
|
+
### 🤖 **Agent-as-Tool Architecture**
|
|
124
|
+
- ✅ **Hierarchical Orchestration**: Use agents as tools in other agents
|
|
125
|
+
- ✅ **Conditional Tool Enabling**: Enable/disable agent tools based on context
|
|
126
|
+
- ✅ **Session Management**: Configurable session inheritance for sub-agents
|
|
127
|
+
- ✅ **Flexible Output Extraction**: Custom extractors for agent tool outputs
|
|
128
|
+
|
|
121
129
|
### 🔧 **Developer Experience**
|
|
122
130
|
- ✅ **CLI Tools**: Project initialization and management
|
|
123
131
|
- ✅ **Hot Reload**: Development server with auto-reload
|
|
124
132
|
- ✅ **Type Hints**: Full mypy compatibility
|
|
125
|
-
- ✅ **Rich Examples**: RAG, multi-agent, and server demos
|
|
133
|
+
- ✅ **Rich Examples**: RAG, multi-agent, agent-as-tool, and server demos
|
|
126
134
|
- ✅ **Visual Architecture**: Graphviz-powered agent and tool diagrams
|
|
127
135
|
|
|
128
136
|
## 🎯 Core Philosophy
|
|
@@ -148,6 +156,7 @@ pip install "jaf-py[all] @ git+https://github.com/xynehq/jaf-py.git"
|
|
|
148
156
|
pip install "jaf-py[server] @ git+https://github.com/xynehq/jaf-py.git" # FastAPI server support
|
|
149
157
|
pip install "jaf-py[memory] @ git+https://github.com/xynehq/jaf-py.git" # Redis/PostgreSQL memory providers
|
|
150
158
|
pip install "jaf-py[visualization] @ git+https://github.com/xynehq/jaf-py.git" # Graphviz visualization tools
|
|
159
|
+
pip install "jaf-py[tracing] @ git+https://github.com/xynehq/jaf-py.git" # OpenTelemetry and Langfuse tracing
|
|
151
160
|
pip install "jaf-py[dev] @ git+https://github.com/xynehq/jaf-py.git" # Development tools
|
|
152
161
|
```
|
|
153
162
|
|
|
@@ -212,6 +221,7 @@ For offline access, documentation is also available in the [`docs/`](docs/) dire
|
|
|
212
221
|
- **[🔧 Tools Guide](docs/tools.md)** - Creating and using tools
|
|
213
222
|
- **[💾 Memory System](docs/memory-system.md)** - Persistence and memory providers
|
|
214
223
|
- **[🤖 Model Providers](docs/model-providers.md)** - LiteLLM integration
|
|
224
|
+
- **[📊 Monitoring](docs/monitoring.md)** - Observability, metrics, and alerting
|
|
215
225
|
- **[🌐 Server API](docs/server-api.md)** - FastAPI endpoints reference
|
|
216
226
|
- **[📦 Deployment](docs/deployment.md)** - Production deployment guide
|
|
217
227
|
- **[🎮 Examples](docs/examples.md)** - Detailed example walkthroughs
|
|
@@ -439,6 +449,58 @@ config = RunConfig(
|
|
|
439
449
|
)
|
|
440
450
|
```
|
|
441
451
|
|
|
452
|
+
## 🤖 Agent-as-Tool Functionality
|
|
453
|
+
|
|
454
|
+
JAF 2.2+ introduces powerful agent-as-tool capabilities, allowing you to use agents as tools within other agents for hierarchical orchestration:
|
|
455
|
+
|
|
456
|
+
```python
|
|
457
|
+
from jaf.core.agent_tool import create_agent_tool
|
|
458
|
+
from jaf.core.types import create_json_output_extractor
|
|
459
|
+
|
|
460
|
+
# Create specialized agents
|
|
461
|
+
spanish_agent = Agent(
|
|
462
|
+
name="spanish_translator",
|
|
463
|
+
instructions=lambda state: "Translate text to Spanish",
|
|
464
|
+
output_codec=TranslationOutput
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
french_agent = Agent(
|
|
468
|
+
name="french_translator",
|
|
469
|
+
instructions=lambda state: "Translate text to French",
|
|
470
|
+
output_codec=TranslationOutput
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
# Convert agents to tools with conditional enabling
|
|
474
|
+
spanish_tool = spanish_agent.as_tool(
|
|
475
|
+
tool_name="translate_to_spanish",
|
|
476
|
+
tool_description="Translate text to Spanish",
|
|
477
|
+
max_turns=3,
|
|
478
|
+
custom_output_extractor=create_json_output_extractor(),
|
|
479
|
+
is_enabled=True # Always enabled
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
french_tool = french_agent.as_tool(
|
|
483
|
+
tool_name="translate_to_french",
|
|
484
|
+
tool_description="Translate text to French",
|
|
485
|
+
max_turns=3,
|
|
486
|
+
custom_output_extractor=create_json_output_extractor(),
|
|
487
|
+
is_enabled=lambda context, agent: context.language_preference == "french_spanish"
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
# Create orchestrator agent using agent tools
|
|
491
|
+
orchestrator = Agent(
|
|
492
|
+
name="translation_orchestrator",
|
|
493
|
+
instructions=lambda state: "Use translation tools to respond in multiple languages",
|
|
494
|
+
tools=[spanish_tool, french_tool]
|
|
495
|
+
)
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### Key Features:
|
|
499
|
+
- **Conditional Enabling**: Enable/disable agent tools based on runtime context
|
|
500
|
+
- **Session Management**: Configure whether sub-agents inherit parent session state
|
|
501
|
+
- **Custom Output Extraction**: Define how to extract and format agent tool outputs
|
|
502
|
+
- **Error Handling**: Robust error handling for failed agent tool executions
|
|
503
|
+
|
|
442
504
|
## 🔗 Agent Handoffs
|
|
443
505
|
|
|
444
506
|
```python
|
|
@@ -488,6 +550,48 @@ config = RunConfig(
|
|
|
488
550
|
)
|
|
489
551
|
```
|
|
490
552
|
|
|
553
|
+
### OpenTelemetry Integration
|
|
554
|
+
|
|
555
|
+
JAF 2.2+ includes built-in OpenTelemetry support for distributed tracing:
|
|
556
|
+
|
|
557
|
+
```python
|
|
558
|
+
import os
|
|
559
|
+
from jaf.core.tracing import create_composite_trace_collector, ConsoleTraceCollector
|
|
560
|
+
|
|
561
|
+
# Configure OpenTelemetry endpoint
|
|
562
|
+
os.environ["TRACE_COLLECTOR_URL"] = "http://localhost:4318/v1/traces"
|
|
563
|
+
|
|
564
|
+
# Tracing will be automatically configured when creating a composite collector
|
|
565
|
+
trace_collector = create_composite_trace_collector(ConsoleTraceCollector())
|
|
566
|
+
|
|
567
|
+
config = RunConfig(
|
|
568
|
+
# ... other config
|
|
569
|
+
on_event=trace_collector.collect,
|
|
570
|
+
)
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### Langfuse Integration
|
|
574
|
+
|
|
575
|
+
For LLM-specific observability and analytics:
|
|
576
|
+
|
|
577
|
+
```python
|
|
578
|
+
import os
|
|
579
|
+
from jaf.core.tracing import create_composite_trace_collector, ConsoleTraceCollector
|
|
580
|
+
|
|
581
|
+
# Configure Langfuse credentials
|
|
582
|
+
os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-your-public-key"
|
|
583
|
+
os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-your-secret-key"
|
|
584
|
+
os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com" # or your self-hosted instance
|
|
585
|
+
|
|
586
|
+
# Langfuse tracing will be automatically configured
|
|
587
|
+
trace_collector = create_composite_trace_collector(ConsoleTraceCollector())
|
|
588
|
+
|
|
589
|
+
config = RunConfig(
|
|
590
|
+
# ... other config
|
|
591
|
+
on_event=trace_collector.collect,
|
|
592
|
+
)
|
|
593
|
+
```
|
|
594
|
+
|
|
491
595
|
### Error Handling
|
|
492
596
|
|
|
493
597
|
```python
|
|
@@ -663,7 +767,41 @@ python server_example.py
|
|
|
663
767
|
- `POST /chat` - Chat with any agent
|
|
664
768
|
- `GET /docs` - Interactive API documentation
|
|
665
769
|
|
|
666
|
-
### 2.
|
|
770
|
+
### 2. Agent-as-Tool Demo
|
|
771
|
+
|
|
772
|
+
```bash
|
|
773
|
+
cd examples
|
|
774
|
+
python agent_as_tool_example.py
|
|
775
|
+
|
|
776
|
+
# Or start as server
|
|
777
|
+
python agent_as_tool_example.py --server
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
**Features demonstrated:**
|
|
781
|
+
- ✅ Hierarchical agent orchestration
|
|
782
|
+
- ✅ Conditional tool enabling based on context
|
|
783
|
+
- ✅ Custom output extraction from agent tools
|
|
784
|
+
- ✅ Session management for sub-agents
|
|
785
|
+
- ✅ Translation agents working together
|
|
786
|
+
|
|
787
|
+
### 3. Tracing Integration Demos
|
|
788
|
+
|
|
789
|
+
```bash
|
|
790
|
+
# OpenTelemetry tracing example
|
|
791
|
+
cd examples
|
|
792
|
+
python otel_tracing_demo.py
|
|
793
|
+
|
|
794
|
+
# Langfuse tracing example
|
|
795
|
+
python langfuse_tracing_demo.py
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
**Features demonstrated:**
|
|
799
|
+
- ✅ OpenTelemetry distributed tracing setup
|
|
800
|
+
- ✅ Langfuse LLM observability integration
|
|
801
|
+
- ✅ Composite trace collectors
|
|
802
|
+
- ✅ Real-time monitoring and analytics
|
|
803
|
+
|
|
804
|
+
### 4. MCP Integration Demo
|
|
667
805
|
|
|
668
806
|
```bash
|
|
669
807
|
cd examples/mcp_demo
|
|
@@ -721,4 +859,4 @@ MIT
|
|
|
721
859
|
|
|
722
860
|
---
|
|
723
861
|
|
|
724
|
-
**JAF (Juspay Agentic Framework) v2.
|
|
862
|
+
**JAF (Juspay Agentic Framework) v2.2** - Building the future of functional AI agent systems 🚀
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<!--  -->
|
|
4
4
|
|
|
5
|
-
[](https://github.com/xynehq/jaf-py)
|
|
6
6
|
[](https://www.python.org/)
|
|
7
7
|
[](https://xynehq.github.io/jaf-py/)
|
|
8
8
|
|
|
@@ -43,15 +43,23 @@ A purely functional agent framework with immutable state and composable tools, p
|
|
|
43
43
|
|
|
44
44
|
### 📊 **Observability & Monitoring**
|
|
45
45
|
- ✅ **Real-time Tracing**: Event-driven observability
|
|
46
|
+
- ✅ **OpenTelemetry Integration**: Distributed tracing with OTLP
|
|
47
|
+
- ✅ **Langfuse Tracing**: LLM observability and analytics
|
|
46
48
|
- ✅ **Structured Logging**: JSON-formatted logs
|
|
47
49
|
- ✅ **Error Handling**: Comprehensive error types and recovery
|
|
48
50
|
- ✅ **Performance Metrics**: Built-in timing and counters
|
|
49
51
|
|
|
52
|
+
### 🤖 **Agent-as-Tool Architecture**
|
|
53
|
+
- ✅ **Hierarchical Orchestration**: Use agents as tools in other agents
|
|
54
|
+
- ✅ **Conditional Tool Enabling**: Enable/disable agent tools based on context
|
|
55
|
+
- ✅ **Session Management**: Configurable session inheritance for sub-agents
|
|
56
|
+
- ✅ **Flexible Output Extraction**: Custom extractors for agent tool outputs
|
|
57
|
+
|
|
50
58
|
### 🔧 **Developer Experience**
|
|
51
59
|
- ✅ **CLI Tools**: Project initialization and management
|
|
52
60
|
- ✅ **Hot Reload**: Development server with auto-reload
|
|
53
61
|
- ✅ **Type Hints**: Full mypy compatibility
|
|
54
|
-
- ✅ **Rich Examples**: RAG, multi-agent, and server demos
|
|
62
|
+
- ✅ **Rich Examples**: RAG, multi-agent, agent-as-tool, and server demos
|
|
55
63
|
- ✅ **Visual Architecture**: Graphviz-powered agent and tool diagrams
|
|
56
64
|
|
|
57
65
|
## 🎯 Core Philosophy
|
|
@@ -77,6 +85,7 @@ pip install "jaf-py[all] @ git+https://github.com/xynehq/jaf-py.git"
|
|
|
77
85
|
pip install "jaf-py[server] @ git+https://github.com/xynehq/jaf-py.git" # FastAPI server support
|
|
78
86
|
pip install "jaf-py[memory] @ git+https://github.com/xynehq/jaf-py.git" # Redis/PostgreSQL memory providers
|
|
79
87
|
pip install "jaf-py[visualization] @ git+https://github.com/xynehq/jaf-py.git" # Graphviz visualization tools
|
|
88
|
+
pip install "jaf-py[tracing] @ git+https://github.com/xynehq/jaf-py.git" # OpenTelemetry and Langfuse tracing
|
|
80
89
|
pip install "jaf-py[dev] @ git+https://github.com/xynehq/jaf-py.git" # Development tools
|
|
81
90
|
```
|
|
82
91
|
|
|
@@ -141,6 +150,7 @@ For offline access, documentation is also available in the [`docs/`](docs/) dire
|
|
|
141
150
|
- **[🔧 Tools Guide](docs/tools.md)** - Creating and using tools
|
|
142
151
|
- **[💾 Memory System](docs/memory-system.md)** - Persistence and memory providers
|
|
143
152
|
- **[🤖 Model Providers](docs/model-providers.md)** - LiteLLM integration
|
|
153
|
+
- **[📊 Monitoring](docs/monitoring.md)** - Observability, metrics, and alerting
|
|
144
154
|
- **[🌐 Server API](docs/server-api.md)** - FastAPI endpoints reference
|
|
145
155
|
- **[📦 Deployment](docs/deployment.md)** - Production deployment guide
|
|
146
156
|
- **[🎮 Examples](docs/examples.md)** - Detailed example walkthroughs
|
|
@@ -368,6 +378,58 @@ config = RunConfig(
|
|
|
368
378
|
)
|
|
369
379
|
```
|
|
370
380
|
|
|
381
|
+
## 🤖 Agent-as-Tool Functionality
|
|
382
|
+
|
|
383
|
+
JAF 2.2+ introduces powerful agent-as-tool capabilities, allowing you to use agents as tools within other agents for hierarchical orchestration:
|
|
384
|
+
|
|
385
|
+
```python
|
|
386
|
+
from jaf.core.agent_tool import create_agent_tool
|
|
387
|
+
from jaf.core.types import create_json_output_extractor
|
|
388
|
+
|
|
389
|
+
# Create specialized agents
|
|
390
|
+
spanish_agent = Agent(
|
|
391
|
+
name="spanish_translator",
|
|
392
|
+
instructions=lambda state: "Translate text to Spanish",
|
|
393
|
+
output_codec=TranslationOutput
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
french_agent = Agent(
|
|
397
|
+
name="french_translator",
|
|
398
|
+
instructions=lambda state: "Translate text to French",
|
|
399
|
+
output_codec=TranslationOutput
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
# Convert agents to tools with conditional enabling
|
|
403
|
+
spanish_tool = spanish_agent.as_tool(
|
|
404
|
+
tool_name="translate_to_spanish",
|
|
405
|
+
tool_description="Translate text to Spanish",
|
|
406
|
+
max_turns=3,
|
|
407
|
+
custom_output_extractor=create_json_output_extractor(),
|
|
408
|
+
is_enabled=True # Always enabled
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
french_tool = french_agent.as_tool(
|
|
412
|
+
tool_name="translate_to_french",
|
|
413
|
+
tool_description="Translate text to French",
|
|
414
|
+
max_turns=3,
|
|
415
|
+
custom_output_extractor=create_json_output_extractor(),
|
|
416
|
+
is_enabled=lambda context, agent: context.language_preference == "french_spanish"
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
# Create orchestrator agent using agent tools
|
|
420
|
+
orchestrator = Agent(
|
|
421
|
+
name="translation_orchestrator",
|
|
422
|
+
instructions=lambda state: "Use translation tools to respond in multiple languages",
|
|
423
|
+
tools=[spanish_tool, french_tool]
|
|
424
|
+
)
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### Key Features:
|
|
428
|
+
- **Conditional Enabling**: Enable/disable agent tools based on runtime context
|
|
429
|
+
- **Session Management**: Configure whether sub-agents inherit parent session state
|
|
430
|
+
- **Custom Output Extraction**: Define how to extract and format agent tool outputs
|
|
431
|
+
- **Error Handling**: Robust error handling for failed agent tool executions
|
|
432
|
+
|
|
371
433
|
## 🔗 Agent Handoffs
|
|
372
434
|
|
|
373
435
|
```python
|
|
@@ -417,6 +479,48 @@ config = RunConfig(
|
|
|
417
479
|
)
|
|
418
480
|
```
|
|
419
481
|
|
|
482
|
+
### OpenTelemetry Integration
|
|
483
|
+
|
|
484
|
+
JAF 2.2+ includes built-in OpenTelemetry support for distributed tracing:
|
|
485
|
+
|
|
486
|
+
```python
|
|
487
|
+
import os
|
|
488
|
+
from jaf.core.tracing import create_composite_trace_collector, ConsoleTraceCollector
|
|
489
|
+
|
|
490
|
+
# Configure OpenTelemetry endpoint
|
|
491
|
+
os.environ["TRACE_COLLECTOR_URL"] = "http://localhost:4318/v1/traces"
|
|
492
|
+
|
|
493
|
+
# Tracing will be automatically configured when creating a composite collector
|
|
494
|
+
trace_collector = create_composite_trace_collector(ConsoleTraceCollector())
|
|
495
|
+
|
|
496
|
+
config = RunConfig(
|
|
497
|
+
# ... other config
|
|
498
|
+
on_event=trace_collector.collect,
|
|
499
|
+
)
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### Langfuse Integration
|
|
503
|
+
|
|
504
|
+
For LLM-specific observability and analytics:
|
|
505
|
+
|
|
506
|
+
```python
|
|
507
|
+
import os
|
|
508
|
+
from jaf.core.tracing import create_composite_trace_collector, ConsoleTraceCollector
|
|
509
|
+
|
|
510
|
+
# Configure Langfuse credentials
|
|
511
|
+
os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-your-public-key"
|
|
512
|
+
os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-your-secret-key"
|
|
513
|
+
os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com" # or your self-hosted instance
|
|
514
|
+
|
|
515
|
+
# Langfuse tracing will be automatically configured
|
|
516
|
+
trace_collector = create_composite_trace_collector(ConsoleTraceCollector())
|
|
517
|
+
|
|
518
|
+
config = RunConfig(
|
|
519
|
+
# ... other config
|
|
520
|
+
on_event=trace_collector.collect,
|
|
521
|
+
)
|
|
522
|
+
```
|
|
523
|
+
|
|
420
524
|
### Error Handling
|
|
421
525
|
|
|
422
526
|
```python
|
|
@@ -592,7 +696,41 @@ python server_example.py
|
|
|
592
696
|
- `POST /chat` - Chat with any agent
|
|
593
697
|
- `GET /docs` - Interactive API documentation
|
|
594
698
|
|
|
595
|
-
### 2.
|
|
699
|
+
### 2. Agent-as-Tool Demo
|
|
700
|
+
|
|
701
|
+
```bash
|
|
702
|
+
cd examples
|
|
703
|
+
python agent_as_tool_example.py
|
|
704
|
+
|
|
705
|
+
# Or start as server
|
|
706
|
+
python agent_as_tool_example.py --server
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
**Features demonstrated:**
|
|
710
|
+
- ✅ Hierarchical agent orchestration
|
|
711
|
+
- ✅ Conditional tool enabling based on context
|
|
712
|
+
- ✅ Custom output extraction from agent tools
|
|
713
|
+
- ✅ Session management for sub-agents
|
|
714
|
+
- ✅ Translation agents working together
|
|
715
|
+
|
|
716
|
+
### 3. Tracing Integration Demos
|
|
717
|
+
|
|
718
|
+
```bash
|
|
719
|
+
# OpenTelemetry tracing example
|
|
720
|
+
cd examples
|
|
721
|
+
python otel_tracing_demo.py
|
|
722
|
+
|
|
723
|
+
# Langfuse tracing example
|
|
724
|
+
python langfuse_tracing_demo.py
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
**Features demonstrated:**
|
|
728
|
+
- ✅ OpenTelemetry distributed tracing setup
|
|
729
|
+
- ✅ Langfuse LLM observability integration
|
|
730
|
+
- ✅ Composite trace collectors
|
|
731
|
+
- ✅ Real-time monitoring and analytics
|
|
732
|
+
|
|
733
|
+
### 4. MCP Integration Demo
|
|
596
734
|
|
|
597
735
|
```bash
|
|
598
736
|
cd examples/mcp_demo
|
|
@@ -650,4 +788,4 @@ MIT
|
|
|
650
788
|
|
|
651
789
|
---
|
|
652
790
|
|
|
653
|
-
**JAF (Juspay Agentic Framework) v2.
|
|
791
|
+
**JAF (Juspay Agentic Framework) v2.2** - Building the future of functional AI agent systems 🚀
|
|
@@ -91,7 +91,13 @@ async def run(
|
|
|
91
91
|
set_current_run_config(config)
|
|
92
92
|
|
|
93
93
|
if config.on_event:
|
|
94
|
-
config.on_event(RunStartEvent(data=to_event_data(RunStartEventData(
|
|
94
|
+
config.on_event(RunStartEvent(data=to_event_data(RunStartEventData(
|
|
95
|
+
run_id=initial_state.run_id,
|
|
96
|
+
trace_id=initial_state.trace_id,
|
|
97
|
+
session_id=config.conversation_id,
|
|
98
|
+
context=initial_state.context,
|
|
99
|
+
messages=initial_state.messages
|
|
100
|
+
))))
|
|
95
101
|
|
|
96
102
|
state_with_memory = await _load_conversation_history(initial_state, config)
|
|
97
103
|
result = await _run_internal(state_with_memory, config)
|
|
@@ -289,7 +295,9 @@ async def _run_internal(
|
|
|
289
295
|
agent_name=current_agent.name,
|
|
290
296
|
model=model,
|
|
291
297
|
trace_id=state.trace_id,
|
|
292
|
-
run_id=state.run_id
|
|
298
|
+
run_id=state.run_id,
|
|
299
|
+
context=state.context,
|
|
300
|
+
messages=state.messages
|
|
293
301
|
))))
|
|
294
302
|
|
|
295
303
|
# Get completion from model provider
|