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.
Files changed (122) hide show
  1. {jaf_py-2.2.3 → jaf_py-2.3.0}/PKG-INFO +143 -5
  2. {jaf_py-2.2.3 → jaf_py-2.3.0}/README.md +142 -4
  3. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/engine.py +10 -2
  4. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/tracing.py +187 -37
  5. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/types.py +5 -0
  6. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/providers/model.py +5 -2
  7. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf_py.egg-info/PKG-INFO +143 -5
  8. {jaf_py-2.2.3 → jaf_py-2.3.0}/pyproject.toml +1 -1
  9. {jaf_py-2.2.3 → jaf_py-2.3.0}/LICENSE +0 -0
  10. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/__init__.py +0 -0
  11. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/__init__.py +0 -0
  12. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/agent.py +0 -0
  13. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/agent_card.py +0 -0
  14. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/client.py +0 -0
  15. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/examples/__init__.py +0 -0
  16. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/examples/client_example.py +0 -0
  17. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/examples/integration_example.py +0 -0
  18. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/examples/rag_demo/__init__.py +0 -0
  19. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/examples/server_demo/__init__.py +0 -0
  20. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/examples/server_example.py +0 -0
  21. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/__init__.py +0 -0
  22. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/cleanup.py +0 -0
  23. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/factory.py +0 -0
  24. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/providers/__init__.py +0 -0
  25. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/providers/composite.py +0 -0
  26. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/providers/in_memory.py +0 -0
  27. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/providers/postgres.py +0 -0
  28. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/providers/redis.py +0 -0
  29. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/serialization.py +0 -0
  30. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/tests/__init__.py +0 -0
  31. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/tests/run_comprehensive_tests.py +0 -0
  32. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/tests/test_cleanup.py +0 -0
  33. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/tests/test_serialization.py +0 -0
  34. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/tests/test_stress_concurrency.py +0 -0
  35. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/tests/test_task_lifecycle.py +0 -0
  36. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/memory/types.py +0 -0
  37. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/protocol.py +0 -0
  38. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/server.py +0 -0
  39. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/standalone_client.py +0 -0
  40. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/__init__.py +0 -0
  41. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/run_tests.py +0 -0
  42. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/test_agent.py +0 -0
  43. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/test_client.py +0 -0
  44. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/test_integration.py +0 -0
  45. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/test_protocol.py +0 -0
  46. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/tests/test_types.py +0 -0
  47. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/a2a/types.py +0 -0
  48. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/cli.py +0 -0
  49. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/__init__.py +0 -0
  50. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/agent_tool.py +0 -0
  51. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/analytics.py +0 -0
  52. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/composition.py +0 -0
  53. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/errors.py +0 -0
  54. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/performance.py +0 -0
  55. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/proxy.py +0 -0
  56. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/proxy_helpers.py +0 -0
  57. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/streaming.py +0 -0
  58. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/tool_results.py +0 -0
  59. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/tools.py +0 -0
  60. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/core/workflows.py +0 -0
  61. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/exceptions.py +0 -0
  62. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/__init__.py +0 -0
  63. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/factory.py +0 -0
  64. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/providers/__init__.py +0 -0
  65. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/providers/in_memory.py +0 -0
  66. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/providers/postgres.py +0 -0
  67. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/providers/redis.py +0 -0
  68. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/types.py +0 -0
  69. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/memory/utils.py +0 -0
  70. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/plugins/__init__.py +0 -0
  71. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/plugins/base.py +0 -0
  72. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/policies/__init__.py +0 -0
  73. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/policies/handoff.py +0 -0
  74. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/policies/validation.py +0 -0
  75. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/providers/__init__.py +0 -0
  76. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/providers/mcp.py +0 -0
  77. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/server/__init__.py +0 -0
  78. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/server/main.py +0 -0
  79. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/server/server.py +0 -0
  80. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/server/types.py +0 -0
  81. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/visualization/__init__.py +0 -0
  82. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/visualization/example.py +0 -0
  83. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/visualization/functional_core.py +0 -0
  84. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/visualization/graphviz.py +0 -0
  85. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/visualization/imperative_shell.py +0 -0
  86. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf/visualization/types.py +0 -0
  87. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf_py.egg-info/SOURCES.txt +0 -0
  88. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf_py.egg-info/dependency_links.txt +0 -0
  89. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf_py.egg-info/entry_points.txt +0 -0
  90. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf_py.egg-info/requires.txt +0 -0
  91. {jaf_py-2.2.3 → jaf_py-2.3.0}/jaf_py.egg-info/top_level.txt +0 -0
  92. {jaf_py-2.2.3 → jaf_py-2.3.0}/setup.cfg +0 -0
  93. {jaf_py-2.2.3 → jaf_py-2.3.0}/setup.py +0 -0
  94. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_a2a_deep.py +0 -0
  95. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_a2a_examples.py +0 -0
  96. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_api_reference_examples.py +0 -0
  97. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_callback_system_examples.py +0 -0
  98. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_coffee_tool.py +0 -0
  99. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_conversation_id_fix.py +0 -0
  100. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_deployment_examples.py +0 -0
  101. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_docs_code_examples.py +0 -0
  102. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_engine.py +0 -0
  103. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_engine_manual.py +0 -0
  104. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_error_handling_examples.py +0 -0
  105. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_getting_started_examples.py +0 -0
  106. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_math_tool.py +0 -0
  107. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_mcp_comprehensive.py +0 -0
  108. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_mcp_docs.py +0 -0
  109. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_mcp_real_functionality.py +0 -0
  110. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_mcp_transports.py +0 -0
  111. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_memory_system_examples.py +0 -0
  112. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_model_providers_examples.py +0 -0
  113. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_property_based.py +0 -0
  114. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_proxy_simple.py +0 -0
  115. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_redis_fixes.py +0 -0
  116. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_redis_memory.py +0 -0
  117. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_server_api_examples.py +0 -0
  118. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_session_continuity.py +0 -0
  119. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_streamable_http_mcp_example.py +0 -0
  120. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_timeout_functionality.py +0 -0
  121. {jaf_py-2.2.3 → jaf_py-2.3.0}/tests/test_tool_integration.py +0 -0
  122. {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.2.3
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
  <!-- ![JAF Banner](docs/cover.png) -->
75
75
 
76
- [![Version](https://img.shields.io/badge/version-2.0.0-blue.svg)](https://github.com/xynehq/jaf-py)
76
+ [![Version](https://img.shields.io/badge/version-2.2.3-blue.svg)](https://github.com/xynehq/jaf-py)
77
77
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
78
78
  [![Docs](https://img.shields.io/badge/Docs-Live-brightgreen)](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. MCP Integration Demo
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.0** - Building the future of functional AI agent systems 🚀
862
+ **JAF (Juspay Agentic Framework) v2.2** - Building the future of functional AI agent systems 🚀
@@ -2,7 +2,7 @@
2
2
 
3
3
  <!-- ![JAF Banner](docs/cover.png) -->
4
4
 
5
- [![Version](https://img.shields.io/badge/version-2.0.0-blue.svg)](https://github.com/xynehq/jaf-py)
5
+ [![Version](https://img.shields.io/badge/version-2.2.3-blue.svg)](https://github.com/xynehq/jaf-py)
6
6
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
7
7
  [![Docs](https://img.shields.io/badge/Docs-Live-brightgreen)](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. MCP Integration Demo
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.0** - Building the future of functional AI agent systems 🚀
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(run_id=initial_state.run_id, trace_id=initial_state.trace_id))))
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