jaf-py 2.6.4__tar.gz → 2.6.6__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 (134) hide show
  1. {jaf_py-2.6.4 → jaf_py-2.6.6}/PKG-INFO +2 -2
  2. {jaf_py-2.6.4 → jaf_py-2.6.6}/README.md +1 -1
  3. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/__init__.py +1 -1
  4. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/agent_tool.py +89 -5
  5. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/tracing.py +1 -1
  6. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/types.py +7 -0
  7. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf_py.egg-info/PKG-INFO +2 -2
  8. {jaf_py-2.6.4 → jaf_py-2.6.6}/pyproject.toml +1 -1
  9. {jaf_py-2.6.4 → jaf_py-2.6.6}/LICENSE +0 -0
  10. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/__init__.py +0 -0
  11. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/agent.py +0 -0
  12. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/agent_card.py +0 -0
  13. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/client.py +0 -0
  14. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/examples/__init__.py +0 -0
  15. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/examples/client_example.py +0 -0
  16. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/examples/integration_example.py +0 -0
  17. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/examples/rag_demo/__init__.py +0 -0
  18. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/examples/server_demo/__init__.py +0 -0
  19. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/examples/server_example.py +0 -0
  20. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/__init__.py +0 -0
  21. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/cleanup.py +0 -0
  22. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/factory.py +0 -0
  23. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/providers/__init__.py +0 -0
  24. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/providers/composite.py +0 -0
  25. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/providers/in_memory.py +0 -0
  26. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/providers/postgres.py +0 -0
  27. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/providers/redis.py +0 -0
  28. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/serialization.py +0 -0
  29. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/tests/__init__.py +0 -0
  30. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/tests/run_comprehensive_tests.py +0 -0
  31. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/tests/test_cleanup.py +0 -0
  32. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/tests/test_serialization.py +0 -0
  33. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/tests/test_stress_concurrency.py +0 -0
  34. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/tests/test_task_lifecycle.py +0 -0
  35. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/memory/types.py +0 -0
  36. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/protocol.py +0 -0
  37. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/server.py +0 -0
  38. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/standalone_client.py +0 -0
  39. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/tests/__init__.py +0 -0
  40. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/tests/run_tests.py +0 -0
  41. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/tests/test_agent.py +0 -0
  42. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/tests/test_client.py +0 -0
  43. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/tests/test_integration.py +0 -0
  44. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/tests/test_protocol.py +0 -0
  45. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/tests/test_types.py +0 -0
  46. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/a2a/types.py +0 -0
  47. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/cli.py +0 -0
  48. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/__init__.py +0 -0
  49. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/analytics.py +0 -0
  50. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/checkpoint.py +0 -0
  51. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/composition.py +0 -0
  52. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/engine.py +0 -0
  53. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/errors.py +0 -0
  54. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/guardrails.py +0 -0
  55. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/handoff.py +0 -0
  56. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/parallel_agents.py +0 -0
  57. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/performance.py +0 -0
  58. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/proxy.py +0 -0
  59. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/proxy_helpers.py +0 -0
  60. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/regeneration.py +0 -0
  61. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/state.py +0 -0
  62. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/streaming.py +0 -0
  63. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/tool_results.py +0 -0
  64. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/tools.py +0 -0
  65. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/core/workflows.py +0 -0
  66. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/exceptions.py +0 -0
  67. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/memory/__init__.py +0 -0
  68. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/memory/approval_storage.py +0 -0
  69. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/memory/factory.py +0 -0
  70. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/memory/providers/__init__.py +0 -0
  71. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/memory/providers/in_memory.py +0 -0
  72. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/memory/providers/postgres.py +0 -0
  73. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/memory/providers/redis.py +0 -0
  74. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/memory/types.py +0 -0
  75. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/memory/utils.py +0 -0
  76. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/plugins/__init__.py +0 -0
  77. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/plugins/base.py +0 -0
  78. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/policies/__init__.py +0 -0
  79. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/policies/handoff.py +0 -0
  80. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/policies/validation.py +0 -0
  81. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/providers/__init__.py +0 -0
  82. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/providers/mcp.py +0 -0
  83. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/providers/model.py +0 -0
  84. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/server/__init__.py +0 -0
  85. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/server/main.py +0 -0
  86. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/server/server.py +0 -0
  87. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/server/types.py +0 -0
  88. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/utils/__init__.py +0 -0
  89. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/utils/attachments.py +0 -0
  90. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/utils/document_processor.py +0 -0
  91. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/visualization/__init__.py +0 -0
  92. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/visualization/example.py +0 -0
  93. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/visualization/functional_core.py +0 -0
  94. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/visualization/graphviz.py +0 -0
  95. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/visualization/imperative_shell.py +0 -0
  96. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf/visualization/types.py +0 -0
  97. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf_py.egg-info/SOURCES.txt +0 -0
  98. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf_py.egg-info/dependency_links.txt +0 -0
  99. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf_py.egg-info/entry_points.txt +0 -0
  100. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf_py.egg-info/requires.txt +0 -0
  101. {jaf_py-2.6.4 → jaf_py-2.6.6}/jaf_py.egg-info/top_level.txt +0 -0
  102. {jaf_py-2.6.4 → jaf_py-2.6.6}/setup.cfg +0 -0
  103. {jaf_py-2.6.4 → jaf_py-2.6.6}/setup.py +0 -0
  104. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_a2a_deep.py +0 -0
  105. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_a2a_examples.py +0 -0
  106. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_api_reference_examples.py +0 -0
  107. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_attachments.py +0 -0
  108. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_callback_system_examples.py +0 -0
  109. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_coffee_tool.py +0 -0
  110. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_conversation_id_fix.py +0 -0
  111. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_deployment_examples.py +0 -0
  112. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_docs_code_examples.py +0 -0
  113. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_engine.py +0 -0
  114. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_engine_manual.py +0 -0
  115. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_error_handling_examples.py +0 -0
  116. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_getting_started_examples.py +0 -0
  117. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_manual.py +0 -0
  118. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_math_tool.py +0 -0
  119. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_mcp_comprehensive.py +0 -0
  120. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_mcp_docs.py +0 -0
  121. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_mcp_real_functionality.py +0 -0
  122. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_mcp_transports.py +0 -0
  123. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_memory_system_examples.py +0 -0
  124. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_model_providers_examples.py +0 -0
  125. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_property_based.py +0 -0
  126. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_proxy_simple.py +0 -0
  127. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_redis_fixes.py +0 -0
  128. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_redis_memory.py +0 -0
  129. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_server_api_examples.py +0 -0
  130. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_session_continuity.py +0 -0
  131. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_streamable_http_mcp_example.py +0 -0
  132. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_timeout_functionality.py +0 -0
  133. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_tool_integration.py +0 -0
  134. {jaf_py-2.6.4 → jaf_py-2.6.6}/tests/test_validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jaf-py
3
- Version: 2.6.4
3
+ Version: 2.6.6
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
@@ -82,7 +82,7 @@ Dynamic: license-file
82
82
 
83
83
  <!-- ![JAF Banner](docs/cover.png) -->
84
84
 
85
- [![Version](https://img.shields.io/badge/version-2.6.4-blue.svg)](https://github.com/xynehq/jaf-py)
85
+ [![Version](https://img.shields.io/badge/version-2.6.6-blue.svg)](https://github.com/xynehq/jaf-py)
86
86
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
87
87
  [![Docs](https://img.shields.io/badge/Docs-Live-brightgreen)](https://xynehq.github.io/jaf-py/)
88
88
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  <!-- ![JAF Banner](docs/cover.png) -->
4
4
 
5
- [![Version](https://img.shields.io/badge/version-2.6.4-blue.svg)](https://github.com/xynehq/jaf-py)
5
+ [![Version](https://img.shields.io/badge/version-2.6.6-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
 
@@ -201,7 +201,7 @@ def generate_run_id() -> RunId:
201
201
  return create_run_id(str(uuid.uuid4()))
202
202
 
203
203
 
204
- __version__ = "2.6.4"
204
+ __version__ = "2.6.6"
205
205
  __all__ = [
206
206
  # Core types and functions
207
207
  "TraceId",
@@ -8,7 +8,6 @@ by other agents, enabling hierarchical agent orchestration patterns.
8
8
  import asyncio
9
9
  import json
10
10
  import inspect
11
- import inspect
12
11
  import contextvars
13
12
  from typing import Any, Callable, Dict, List, Optional, Union, Awaitable, TypeVar, get_type_hints
14
13
 
@@ -79,6 +78,7 @@ def create_agent_tool(
79
78
  metadata: Optional[Dict[str, Any]] = None,
80
79
  timeout: Optional[float] = None,
81
80
  preserve_session: bool = False,
81
+ preserve_session_id: bool = False,
82
82
  ) -> Tool[AgentToolInput, Ctx]:
83
83
  """
84
84
  Create a tool from an agent.
@@ -92,6 +92,10 @@ def create_agent_tool(
92
92
  is_enabled: Whether the tool is enabled (bool, sync function, or async function)
93
93
  metadata: Optional metadata for the tool
94
94
  timeout: Optional timeout for tool execution
95
+ preserve_session: When True, inherit parent's conversation_id AND memory (shared session)
96
+ preserve_session_id: When True, inherit ONLY parent's conversation_id for tracing (no memory).
97
+ This allows subagent traces to appear together in Langfuse without
98
+ loading previous invocation history. Mutually exclusive with preserve_session.
95
99
 
96
100
  Returns:
97
101
  A Tool that wraps the agent execution
@@ -181,18 +185,98 @@ def create_agent_tool(
181
185
  # Session inheritance is configurable via preserve_session.
182
186
  # - When True: inherit parent's conversation_id and memory (shared memory/session)
183
187
  # - When False: do not inherit (ephemeral, per-invocation sub-agent run)
188
+ #
189
+ # Model selection for subagents:
190
+ # - If subagent has its own model_config, use that model AND create appropriate provider
191
+ # - If subagent has no model_config, inherit parent's model_override and provider
192
+ # This allows subagents to run on different models than the parent agent
193
+ subagent_model_override = None
194
+ subagent_model_provider = parent_config.model_provider
195
+
196
+ if agent.model_config and agent.model_config.name:
197
+ subagent_model_name = agent.model_config.name
198
+ # Subagent has explicit model_config - create appropriate provider for it
199
+ # Use model_override to force the subagent's model
200
+ subagent_model_override = subagent_model_name
201
+
202
+ # Create provider based on model type
203
+ import os
204
+ if subagent_model_name.startswith("azure/"):
205
+ try:
206
+ from jaf.providers import make_litellm_sdk_provider
207
+ azure_api_key = os.getenv("AZURE_API_KEY")
208
+ azure_api_base = os.getenv("AZURE_API_BASE")
209
+ azure_api_version = os.getenv("AZURE_API_VERSION")
210
+ subagent_model_provider = make_litellm_sdk_provider(
211
+ model=subagent_model_name,
212
+ api_key=azure_api_key,
213
+ base_url=azure_api_base,
214
+ api_version=azure_api_version,
215
+ )
216
+ except Exception as e:
217
+ # Fallback to parent provider if Azure provider creation fails
218
+ subagent_model_provider = parent_config.model_provider
219
+ elif subagent_model_name.startswith("vertex_ai/"):
220
+ try:
221
+ from jaf.providers import make_litellm_sdk_provider
222
+ vertex_project = os.getenv("VERTEXAI_PROJECT")
223
+ vertex_location = os.getenv("VERTEXAI_LOCATION")
224
+ if not vertex_project or not vertex_location:
225
+ raise ValueError(
226
+ "VERTEXAI_PROJECT and VERTEXAI_LOCATION environment variables are required for vertex_ai/ models"
227
+ )
228
+ subagent_model_provider = make_litellm_sdk_provider(
229
+ model=subagent_model_name,
230
+ vertex_project=vertex_project,
231
+ vertex_location=vertex_location,
232
+ )
233
+ except Exception:
234
+ subagent_model_provider = parent_config.model_provider
235
+ elif subagent_model_name.startswith("glm"):
236
+ try:
237
+ from jaf.providers import make_litellm_provider
238
+ subagent_model_provider = make_litellm_provider(
239
+ base_url=os.getenv("LITELLM_BASE_URL"),
240
+ api_key=os.getenv("LITELLM_KEY")
241
+ )
242
+ except Exception:
243
+ subagent_model_provider = parent_config.model_provider
244
+ # For other models, use parent's provider (may work or may not)
245
+ else:
246
+ # No subagent model_config - inherit from parent
247
+ subagent_model_override = parent_config.model_override
248
+ subagent_model_provider = parent_config.model_provider
249
+
250
+ # Determine conversation_id and memory inheritance based on session preservation settings:
251
+ # - preserve_session=True: inherit both conversation_id AND memory (full shared session)
252
+ # - preserve_session_id=True: inherit ONLY conversation_id for tracing (no memory, stateless calls)
253
+ # - Both False: completely ephemeral sub-agent run
254
+ #
255
+ # preserve_session_id is useful when you want:
256
+ # 1. Subagent traces to appear together in Langfuse under the same conversation
257
+ # 2. But each subagent invocation to be stateless (no accumulated history from previous calls)
258
+ if preserve_session:
259
+ subagent_memory = parent_config.memory
260
+ subagent_conversation_id = parent_config.conversation_id
261
+ elif preserve_session_id:
262
+ subagent_memory = None # No memory inheritance - stateless
263
+ subagent_conversation_id = parent_config.conversation_id # Only for tracing
264
+ else:
265
+ subagent_memory = None
266
+ subagent_conversation_id = None
267
+
184
268
  sub_config = RunConfig(
185
269
  agent_registry={agent.name: agent, **parent_config.agent_registry},
186
- model_provider=parent_config.model_provider,
270
+ model_provider=subagent_model_provider,
187
271
  max_turns=max_turns or parent_config.max_turns,
188
- model_override=parent_config.model_override,
272
+ model_override=subagent_model_override,
189
273
  initial_input_guardrails=parent_config.initial_input_guardrails,
190
274
  final_output_guardrails=parent_config.final_output_guardrails,
191
275
  on_event=parent_config.on_event,
192
276
  before_llm_call=parent_config.before_llm_call,
193
277
  after_llm_call=parent_config.after_llm_call,
194
- memory=parent_config.memory if preserve_session else None,
195
- conversation_id=parent_config.conversation_id if preserve_session else None,
278
+ memory=subagent_memory,
279
+ conversation_id=subagent_conversation_id,
196
280
  default_tool_timeout=parent_config.default_tool_timeout,
197
281
  prefer_streaming=parent_config.prefer_streaming,
198
282
  )
@@ -469,7 +469,7 @@ class LangfuseTraceCollector:
469
469
  public_key=public_key,
470
470
  secret_key=secret_key,
471
471
  host=host,
472
- release="jaf-py-v2.6.4",
472
+ release="jaf-py-v2.6.6",
473
473
  httpx_client=client,
474
474
  )
475
475
  self._httpx_client = client
@@ -428,6 +428,7 @@ class Agent(Generic[Ctx, Out]):
428
428
  metadata: Optional[Dict[str, Any]] = None,
429
429
  timeout: Optional[float] = None,
430
430
  preserve_session: bool = False,
431
+ preserve_session_id: bool = False,
431
432
  ) -> Tool[Any, Ctx]:
432
433
  """
433
434
  Convert this agent into a tool that can be used by other agents.
@@ -440,6 +441,11 @@ class Agent(Generic[Ctx, Out]):
440
441
  is_enabled: Whether the tool is enabled (bool, sync function, or async function)
441
442
  metadata: Optional metadata for the tool
442
443
  timeout: Optional timeout for the tool execution
444
+ preserve_session: When True, inherit parent's conversation_id AND memory (shared session)
445
+ preserve_session_id: When True, inherit ONLY parent's conversation_id for tracing (no memory).
446
+ This allows subagent traces to appear together in Langfuse without
447
+ loading previous invocation history. Useful for stateless subagent calls
448
+ that should still be grouped together in traces.
443
449
 
444
450
  Returns:
445
451
  A Tool that wraps this agent's execution
@@ -456,6 +462,7 @@ class Agent(Generic[Ctx, Out]):
456
462
  metadata=metadata,
457
463
  timeout=timeout,
458
464
  preserve_session=preserve_session,
465
+ preserve_session_id=preserve_session_id,
459
466
  )
460
467
 
461
468
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jaf-py
3
- Version: 2.6.4
3
+ Version: 2.6.6
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
@@ -82,7 +82,7 @@ Dynamic: license-file
82
82
 
83
83
  <!-- ![JAF Banner](docs/cover.png) -->
84
84
 
85
- [![Version](https://img.shields.io/badge/version-2.6.4-blue.svg)](https://github.com/xynehq/jaf-py)
85
+ [![Version](https://img.shields.io/badge/version-2.6.6-blue.svg)](https://github.com/xynehq/jaf-py)
86
86
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
87
87
  [![Docs](https://img.shields.io/badge/Docs-Live-brightgreen)](https://xynehq.github.io/jaf-py/)
88
88
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jaf-py"
7
- version = "2.6.4"
7
+ version = "2.6.6"
8
8
  description = "A purely functional agent framework with immutable state and composable tools - Python implementation"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes