unique_toolkit 1.10.0__tar.gz → 1.11.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 (155) hide show
  1. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/CHANGELOG.md +4 -2
  2. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/PKG-INFO +5 -2
  3. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/pyproject.toml +1 -1
  4. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/__init__.py +6 -0
  5. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/postprocessing/postprocessor.py +31 -2
  6. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_consolidate_references.py +60 -33
  7. unique_toolkit-1.11.0/unique_toolkit/agentic/tools/a2a/prompts.py +46 -0
  8. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/tool/config.py +5 -5
  9. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/tool/service.py +28 -1
  10. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/LICENSE +0 -0
  11. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/README.md +0 -0
  12. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/__init__.py +0 -0
  13. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/_base_service.py +0 -0
  14. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/_time_utils.py +0 -0
  15. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/api_calling/human_verification_manager.py +0 -0
  16. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/base_model_type_attribute.py +0 -0
  17. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/chunk_relevancy_sorter/config.py +0 -0
  18. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/chunk_relevancy_sorter/exception.py +0 -0
  19. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/chunk_relevancy_sorter/schemas.py +0 -0
  20. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/chunk_relevancy_sorter/service.py +0 -0
  21. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/chunk_relevancy_sorter/tests/test_service.py +0 -0
  22. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/default_language_model.py +0 -0
  23. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/endpoint_builder.py +0 -0
  24. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/endpoint_requestor.py +0 -0
  25. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/exception.py +0 -0
  26. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/feature_flags/schema.py +0 -0
  27. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/pydantic/rjsf_tags.py +0 -0
  28. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/pydantic_helpers.py +0 -0
  29. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/string_utilities.py +0 -0
  30. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/token/image_token_counting.py +0 -0
  31. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/token/token_counting.py +0 -0
  32. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/utils/__init__.py +0 -0
  33. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/utils/files.py +0 -0
  34. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/utils/structured_output/__init__.py +0 -0
  35. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/utils/structured_output/schema.py +0 -0
  36. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/utils/write_configuration.py +0 -0
  37. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/validate_required_values.py +0 -0
  38. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/_common/validators.py +0 -0
  39. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/__init__.py +0 -0
  40. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/debug_info_manager/debug_info_manager.py +0 -0
  41. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/config.py +0 -0
  42. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/context_relevancy/prompts.py +0 -0
  43. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/context_relevancy/schema.py +0 -0
  44. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/context_relevancy/service.py +0 -0
  45. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/evaluation_manager.py +0 -0
  46. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/exception.py +0 -0
  47. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/hallucination/constants.py +0 -0
  48. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/hallucination/hallucination_evaluation.py +0 -0
  49. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/hallucination/prompts.py +0 -0
  50. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/hallucination/service.py +0 -0
  51. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/hallucination/utils.py +0 -0
  52. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/output_parser.py +0 -0
  53. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/schemas.py +0 -0
  54. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/tests/test_context_relevancy_service.py +0 -0
  55. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/evaluation/tests/test_output_parser.py +0 -0
  56. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/history_manager/history_construction_with_contents.py +0 -0
  57. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/history_manager/history_manager.py +0 -0
  58. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/history_manager/loop_token_reducer.py +0 -0
  59. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/history_manager/utils.py +0 -0
  60. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/postprocessor/postprocessor_manager.py +0 -0
  61. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/reference_manager/reference_manager.py +0 -0
  62. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/short_term_memory_manager/persistent_short_term_memory_manager.py +0 -0
  63. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/thinking_manager/thinking_manager.py +0 -0
  64. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/__init__.py +0 -0
  65. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/config.py +0 -0
  66. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/evaluation/__init__.py +0 -0
  67. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/evaluation/_utils.py +0 -0
  68. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/evaluation/config.py +0 -0
  69. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py +0 -0
  70. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2 +0 -0
  71. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/manager.py +0 -0
  72. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py +0 -0
  73. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/postprocessing/_display.py +0 -0
  74. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/postprocessing/_utils.py +0 -0
  75. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/postprocessing/config.py +0 -0
  76. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_display.py +0 -0
  77. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/postprocessing/test/test_postprocessor_reference_functions.py +0 -0
  78. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/tool/__init__.py +0 -0
  79. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/tool/_memory.py +0 -0
  80. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/a2a/tool/_schema.py +0 -0
  81. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/agent_chunks_hanlder.py +0 -0
  82. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/config.py +0 -0
  83. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/factory.py +0 -0
  84. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/mcp/__init__.py +0 -0
  85. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/mcp/manager.py +0 -0
  86. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/mcp/models.py +0 -0
  87. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/mcp/tool_wrapper.py +0 -0
  88. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/schemas.py +0 -0
  89. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/test/test_mcp_manager.py +0 -0
  90. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py +0 -0
  91. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/tool.py +0 -0
  92. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/tool_manager.py +0 -0
  93. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/tool_progress_reporter.py +0 -0
  94. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/utils/__init__.py +0 -0
  95. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/utils/execution/__init__.py +0 -0
  96. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/utils/execution/execution.py +0 -0
  97. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/utils/source_handling/__init__.py +0 -0
  98. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/utils/source_handling/schema.py +0 -0
  99. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py +0 -0
  100. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py +0 -0
  101. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/app/__init__.py +0 -0
  102. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/app/dev_util.py +0 -0
  103. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/app/init_logging.py +0 -0
  104. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/app/init_sdk.py +0 -0
  105. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/app/performance/async_tasks.py +0 -0
  106. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/app/performance/async_wrapper.py +0 -0
  107. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/app/schemas.py +0 -0
  108. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/app/unique_settings.py +0 -0
  109. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/app/verification.py +0 -0
  110. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/chat/__init__.py +0 -0
  111. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/chat/constants.py +0 -0
  112. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/chat/deprecated/service.py +0 -0
  113. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/chat/functions.py +0 -0
  114. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/chat/schemas.py +0 -0
  115. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/chat/service.py +0 -0
  116. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/chat/state.py +0 -0
  117. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/chat/utils.py +0 -0
  118. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/content/__init__.py +0 -0
  119. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/content/constants.py +0 -0
  120. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/content/functions.py +0 -0
  121. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/content/schemas.py +0 -0
  122. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/content/service.py +0 -0
  123. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/content/utils.py +0 -0
  124. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/embedding/__init__.py +0 -0
  125. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/embedding/constants.py +0 -0
  126. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/embedding/functions.py +0 -0
  127. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/embedding/schemas.py +0 -0
  128. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/embedding/service.py +0 -0
  129. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/embedding/utils.py +0 -0
  130. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/framework_utilities/__init__.py +0 -0
  131. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/framework_utilities/langchain/client.py +0 -0
  132. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/framework_utilities/langchain/history.py +0 -0
  133. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/framework_utilities/openai/__init__.py +0 -0
  134. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/framework_utilities/openai/client.py +0 -0
  135. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/framework_utilities/openai/message_builder.py +0 -0
  136. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/framework_utilities/utils.py +0 -0
  137. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/knowledge_base.py +0 -0
  138. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/language_model/__init__.py +0 -0
  139. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/language_model/builder.py +0 -0
  140. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/language_model/constants.py +0 -0
  141. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/language_model/functions.py +0 -0
  142. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/language_model/infos.py +0 -0
  143. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/language_model/prompt.py +0 -0
  144. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/language_model/reference.py +0 -0
  145. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/language_model/schemas.py +0 -0
  146. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/language_model/service.py +0 -0
  147. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/language_model/utils.py +0 -0
  148. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/protocols/support.py +0 -0
  149. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/short_term_memory/__init__.py +0 -0
  150. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/short_term_memory/constants.py +0 -0
  151. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/short_term_memory/functions.py +0 -0
  152. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/short_term_memory/schemas.py +0 -0
  153. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/short_term_memory/service.py +0 -0
  154. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/smart_rules/__init__.py +0 -0
  155. {unique_toolkit-1.10.0 → unique_toolkit-1.11.0}/unique_toolkit/smart_rules/compile.py +0 -0
@@ -5,8 +5,10 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.11.0] - 2025-10-07
9
+ - Add sub-agent response referencing.
8
10
 
9
- ## 1.10.0 - 2025-10-07
11
+ ## [1.10.0] - 2025-10-07
10
12
  - Introduce future proof knowledgebase service decoupled from chat
11
13
  - Extend chat service to download contents in the chat
12
14
  - Update documentation
@@ -733,4 +735,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
733
735
  - `utils.py` with utility functions for parsing language model output.
734
736
 
735
737
  ## [0.0.2] - 2024-07-10
736
- - Initial release of `unique_toolkit`.
738
+ - Initial release of `unique_toolkit`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_toolkit
3
- Version: 1.10.0
3
+ Version: 1.11.0
4
4
  Summary:
5
5
  License: Proprietary
6
6
  Author: Cedric Klinkert
@@ -118,8 +118,10 @@ All notable changes to this project will be documented in this file.
118
118
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
119
119
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
120
120
 
121
+ ## [1.11.0] - 2025-10-07
122
+ - Add sub-agent response referencing.
121
123
 
122
- ## 1.10.0 - 2025-10-07
124
+ ## [1.10.0] - 2025-10-07
123
125
  - Introduce future proof knowledgebase service decoupled from chat
124
126
  - Extend chat service to download contents in the chat
125
127
  - Update documentation
@@ -847,3 +849,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
847
849
 
848
850
  ## [0.0.2] - 2024-07-10
849
851
  - Initial release of `unique_toolkit`.
852
+
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "unique_toolkit"
3
- version = "1.10.0"
3
+ version = "1.11.0"
4
4
  description = ""
5
5
  authors = [
6
6
  "Cedric Klinkert <cedric.klinkert@unique.ch>",
@@ -7,6 +7,10 @@ from unique_toolkit.agentic.tools.a2a.manager import A2AManager
7
7
  from unique_toolkit.agentic.tools.a2a.postprocessing import (
8
8
  SubAgentResponsesPostprocessor,
9
9
  )
10
+ from unique_toolkit.agentic.tools.a2a.prompts import (
11
+ REFERENCING_INSTRUCTIONS_FOR_SYSTEM_PROMPT,
12
+ REFERENCING_INSTRUCTIONS_FOR_USER_PROMPT,
13
+ )
10
14
  from unique_toolkit.agentic.tools.a2a.tool import SubAgentTool, SubAgentToolConfig
11
15
 
12
16
  __all__ = [
@@ -17,4 +21,6 @@ __all__ = [
17
21
  "ExtendedSubAgentToolConfig",
18
22
  "SubAgentEvaluationServiceConfig",
19
23
  "SubAgentEvaluationService",
24
+ "REFERENCING_INSTRUCTIONS_FOR_SYSTEM_PROMPT",
25
+ "REFERENCING_INSTRUCTIONS_FOR_USER_PROMPT",
20
26
  ]
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ import re
2
3
  from typing import TypedDict, override
3
4
 
4
5
  import unique_sdk
@@ -30,6 +31,7 @@ class _SubAgentMessageInfo(TypedDict):
30
31
 
31
32
 
32
33
  class _SubAgentToolInfo(TypedDict):
34
+ name: str
33
35
  display_name: str
34
36
  display_config: SubAgentDisplayConfig
35
37
  responses: dict[int, _SubAgentMessageInfo]
@@ -83,7 +85,7 @@ class SubAgentResponsesPostprocessor(Postprocessor):
83
85
  }
84
86
 
85
87
  _consolidate_references_in_place(
86
- list(self._assistant_id_to_tool_info.values()), existing_refs
88
+ list(self._assistant_id_to_tool_info.values()), existing_refs, loop_response
87
89
  )
88
90
 
89
91
  answers = []
@@ -151,6 +153,7 @@ class SubAgentResponsesPostprocessor(Postprocessor):
151
153
  self._assistant_id_to_tool_info[tool.config.assistant_id] = (
152
154
  _SubAgentToolInfo(
153
155
  display_config=display_config,
156
+ name=tool.name,
154
157
  display_name=tool.display_name(),
155
158
  responses={},
156
159
  )
@@ -192,7 +195,9 @@ class SubAgentResponsesPostprocessor(Postprocessor):
192
195
 
193
196
 
194
197
  def _consolidate_references_in_place(
195
- messages: list[_SubAgentToolInfo], existing_refs: dict[str, int]
198
+ messages: list[_SubAgentToolInfo],
199
+ existing_refs: dict[str, int],
200
+ loop_response: LanguageModelStreamResponse,
196
201
  ) -> None:
197
202
  start_index = max(existing_refs.values(), default=0) + 1
198
203
 
@@ -226,5 +231,29 @@ def _consolidate_references_in_place(
226
231
  ref_map[reference["sequenceNumber"]] = reference_num
227
232
  reference["sequenceNumber"] = reference_num
228
233
 
234
+ loop_response.message.text = (
235
+ _replace_sub_agent_references_in_main_agent_message(
236
+ loop_response.message.text,
237
+ assistant_tool_info["name"],
238
+ sequence_number,
239
+ ref_map,
240
+ )
241
+ )
229
242
  message["text"] = _replace_references_in_text(message["text"], ref_map)
230
243
  message["references"] = message_new_refs
244
+
245
+
246
+ def _replace_sub_agent_references_in_main_agent_message(
247
+ message: str, sub_agent_name: str, sequence_number: int, ref_map: dict[int, int]
248
+ ) -> str:
249
+ for old_seq_num, new_seq_num in ref_map.items():
250
+ reference = SubAgentTool.get_sub_agent_reference_format(
251
+ name=sub_agent_name,
252
+ sequence_number=sequence_number,
253
+ reference_number=old_seq_num,
254
+ )
255
+ message = re.sub(rf"\s*{reference}", f" <sup>{new_seq_num}</sup>", message)
256
+
257
+ # Remove spaces between consecutive references
258
+ message = re.sub(r"</sup>\s*<sup>", "</sup><sup>", message)
259
+ return message
@@ -1,4 +1,4 @@
1
- from unittest.mock import patch
1
+ from unittest.mock import MagicMock, patch
2
2
 
3
3
  import pytest
4
4
 
@@ -10,12 +10,21 @@ from unique_toolkit.agentic.tools.a2a.postprocessing.postprocessor import (
10
10
  class TestConsolidateReferencesInPlace:
11
11
  """Test cases for _consolidate_references_in_place function."""
12
12
 
13
+ def _create_mock_loop_response(self, text: str = "Test response") -> MagicMock:
14
+ """Create a mock LanguageModelStreamResponse object."""
15
+ mock_response = MagicMock()
16
+ mock_message = MagicMock()
17
+ mock_message.text = text
18
+ mock_response.message = mock_message
19
+ return mock_response
20
+
13
21
  def test_empty_messages_list(self):
14
22
  """Test with empty messages list."""
15
23
  messages = []
16
24
  existing_refs = {}
25
+ loop_response = self._create_mock_loop_response()
17
26
 
18
- _consolidate_references_in_place(messages, existing_refs)
27
+ _consolidate_references_in_place(messages, existing_refs, loop_response)
19
28
 
20
29
  assert existing_refs == {}
21
30
 
@@ -23,6 +32,7 @@ class TestConsolidateReferencesInPlace:
23
32
  """Test with empty existing references."""
24
33
  messages = [
25
34
  {
35
+ "name": "Assistant1",
26
36
  "display_name": "Assistant1",
27
37
  "display_config": {"mode": "expanded"},
28
38
  "responses": {
@@ -43,8 +53,9 @@ class TestConsolidateReferencesInPlace:
43
53
  }
44
54
  ]
45
55
  existing_refs = {}
56
+ loop_response = self._create_mock_loop_response()
46
57
 
47
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
58
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
48
59
 
49
60
  # Should start from index 1 since existing_refs is empty
50
61
  assert existing_refs == {"source1": 1}
@@ -58,6 +69,7 @@ class TestConsolidateReferencesInPlace:
58
69
  """Test with existing references."""
59
70
  messages = [
60
71
  {
72
+ "name": "Assistant1",
61
73
  "display_name": "Assistant1",
62
74
  "display_config": {"mode": "expanded"},
63
75
  "responses": {
@@ -78,8 +90,9 @@ class TestConsolidateReferencesInPlace:
78
90
  }
79
91
  ]
80
92
  existing_refs = {"existing_source": 5}
93
+ loop_response = self._create_mock_loop_response()
81
94
 
82
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
95
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
83
96
 
84
97
  # Should start from 6 (max existing + 1)
85
98
  assert existing_refs == {"existing_source": 5, "new_source": 6}
@@ -93,6 +106,7 @@ class TestConsolidateReferencesInPlace:
93
106
  """Test with duplicate source IDs across different messages."""
94
107
  messages = [
95
108
  {
109
+ "name": "Assistant1",
96
110
  "display_name": "Assistant1",
97
111
  "display_config": {"mode": "expanded"},
98
112
  "responses": {
@@ -127,7 +141,8 @@ class TestConsolidateReferencesInPlace:
127
141
  ]
128
142
  existing_refs = {}
129
143
 
130
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
144
+ loop_response = self._create_mock_loop_response()
145
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
131
146
 
132
147
  # Both should map to the same consolidated reference number
133
148
  assert existing_refs == {"shared_source": 1}
@@ -142,6 +157,7 @@ class TestConsolidateReferencesInPlace:
142
157
  """Test with multiple references in a single message."""
143
158
  messages = [
144
159
  {
160
+ "name": "Assistant1",
145
161
  "display_name": "Assistant1",
146
162
  "display_config": {"mode": "expanded"},
147
163
  "responses": {
@@ -171,7 +187,8 @@ class TestConsolidateReferencesInPlace:
171
187
  ]
172
188
  existing_refs = {}
173
189
 
174
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
190
+ loop_response = self._create_mock_loop_response()
191
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
175
192
 
176
193
  assert existing_refs == {"source1": 1, "source2": 2}
177
194
  # Both references should be in the message since they're unique
@@ -185,6 +202,7 @@ class TestConsolidateReferencesInPlace:
185
202
  """Test that references are sorted by sequence number before processing."""
186
203
  messages = [
187
204
  {
205
+ "name": "Assistant1",
188
206
  "display_name": "Assistant1",
189
207
  "display_config": {"mode": "expanded"},
190
208
  "responses": {
@@ -222,7 +240,8 @@ class TestConsolidateReferencesInPlace:
222
240
  ]
223
241
  existing_refs = {}
224
242
 
225
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
243
+ loop_response = self._create_mock_loop_response()
244
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
226
245
 
227
246
  # Should be processed in order 1, 2, 3 and assigned consecutive numbers
228
247
  assert existing_refs == {"source1": 1, "source2": 2, "source3": 3}
@@ -235,6 +254,7 @@ class TestConsolidateReferencesInPlace:
235
254
  """Test with empty references list."""
236
255
  messages = [
237
256
  {
257
+ "name": "Assistant1",
238
258
  "display_name": "Assistant1",
239
259
  "display_config": {"mode": "expanded"},
240
260
  "responses": {1: {"text": "Text with no references", "references": []}},
@@ -242,16 +262,8 @@ class TestConsolidateReferencesInPlace:
242
262
  ]
243
263
  existing_refs = {}
244
264
 
245
- with patch(
246
- "unique_toolkit.agentic.tools.a2a.postprocessing.postprocessor.logger"
247
- ) as mock_logger:
248
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
249
-
250
- # Should log debug message about no references
251
- mock_logger.debug.assert_called_once()
252
- assert (
253
- "does not contain any references" in mock_logger.debug.call_args[0][0]
254
- )
265
+ loop_response = self._create_mock_loop_response()
266
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
255
267
 
256
268
  assert existing_refs == {}
257
269
  assert messages[0]["responses"][1]["text"] == "Text with no references"
@@ -260,6 +272,7 @@ class TestConsolidateReferencesInPlace:
260
272
  """Test with multiple assistants."""
261
273
  messages = [
262
274
  {
275
+ "name": "Assistant1",
263
276
  "display_name": "Assistant1",
264
277
  "display_config": {"mode": "expanded"},
265
278
  "responses": {
@@ -279,6 +292,7 @@ class TestConsolidateReferencesInPlace:
279
292
  },
280
293
  },
281
294
  {
295
+ "name": "Assistant2",
282
296
  "display_name": "Assistant2",
283
297
  "display_config": {"mode": "expanded"},
284
298
  "responses": {
@@ -300,7 +314,8 @@ class TestConsolidateReferencesInPlace:
300
314
  ]
301
315
  existing_refs = {}
302
316
 
303
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
317
+ loop_response = self._create_mock_loop_response()
318
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
304
319
 
305
320
  assert existing_refs == {"source1": 1, "source2": 2}
306
321
  assert messages[0]["responses"][1]["text"] == "Assistant 1 text <sup>1</sup>"
@@ -310,6 +325,7 @@ class TestConsolidateReferencesInPlace:
310
325
  """Test complex scenario with overlapping sequence numbers and mixed source IDs."""
311
326
  messages = [
312
327
  {
328
+ "name": "Assistant1",
313
329
  "display_name": "Assistant1",
314
330
  "display_config": {"mode": "expanded"},
315
331
  "responses": {
@@ -352,7 +368,8 @@ class TestConsolidateReferencesInPlace:
352
368
  ]
353
369
  existing_refs = {"existing": 10} # Start from 11
354
370
 
355
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
371
+ loop_response = self._create_mock_loop_response()
372
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
356
373
 
357
374
  # sourceB gets 11 (first in sorted order), sourceA gets 12
358
375
  assert existing_refs == {"existing": 10, "sourceB": 11, "sourceA": 12}
@@ -377,6 +394,7 @@ class TestConsolidateReferencesInPlace:
377
394
 
378
395
  messages = [
379
396
  {
397
+ "name": "Assistant1",
380
398
  "display_name": "Assistant1",
381
399
  "display_config": {"mode": "expanded"},
382
400
  "responses": {
@@ -398,7 +416,8 @@ class TestConsolidateReferencesInPlace:
398
416
  ]
399
417
  existing_refs = {}
400
418
 
401
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
419
+ loop_response = self._create_mock_loop_response()
420
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
402
421
 
403
422
  # Should call _replace_references_in_text with the original text and ref mapping
404
423
  mock_replace.assert_called_once_with("Original text <sup>1</sup>", {1: 1})
@@ -417,6 +436,7 @@ class TestConsolidateReferencesInPlace:
417
436
 
418
437
  messages = [
419
438
  {
439
+ "name": "Assistant1",
420
440
  "display_name": "Assistant1",
421
441
  "display_config": {"mode": "expanded"},
422
442
  "responses": {
@@ -426,7 +446,8 @@ class TestConsolidateReferencesInPlace:
426
446
  ]
427
447
  existing_refs = {}
428
448
 
429
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
449
+ loop_response = self._create_mock_loop_response()
450
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
430
451
 
431
452
  # The original reference object should be modified in place
432
453
  assert original_ref["sequenceNumber"] == 1
@@ -445,6 +466,7 @@ class TestConsolidateReferencesInPlace:
445
466
  """Test that start_index is calculated correctly from existing_refs."""
446
467
  messages = [
447
468
  {
469
+ "name": "Assistant1",
448
470
  "display_name": "Assistant1",
449
471
  "display_config": {"mode": "expanded"},
450
472
  "responses": {
@@ -466,7 +488,8 @@ class TestConsolidateReferencesInPlace:
466
488
  ]
467
489
 
468
490
  existing_refs_copy = existing_refs.copy()
469
- _consolidate_references_in_place(messages, existing_refs_copy) # type: ignore
491
+ loop_response = self._create_mock_loop_response()
492
+ _consolidate_references_in_place(messages, existing_refs_copy, loop_response) # type: ignore
470
493
 
471
494
  assert existing_refs_copy["new_source"] == expected_start
472
495
 
@@ -474,6 +497,7 @@ class TestConsolidateReferencesInPlace:
474
497
  """Test with assistant that has no responses."""
475
498
  messages = [
476
499
  {
500
+ "name": "Assistant1",
477
501
  "display_name": "Assistant1",
478
502
  "display_config": {"mode": "expanded"},
479
503
  "responses": {},
@@ -481,7 +505,8 @@ class TestConsolidateReferencesInPlace:
481
505
  ]
482
506
  existing_refs = {}
483
507
 
484
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
508
+ loop_response = self._create_mock_loop_response()
509
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
485
510
 
486
511
  assert existing_refs == {}
487
512
 
@@ -489,6 +514,7 @@ class TestConsolidateReferencesInPlace:
489
514
  """Test with mix of valid messages and messages with no references."""
490
515
  messages = [
491
516
  {
517
+ "name": "Assistant1",
492
518
  "display_name": "Assistant1",
493
519
  "display_config": {"mode": "expanded"},
494
520
  "responses": {
@@ -524,13 +550,8 @@ class TestConsolidateReferencesInPlace:
524
550
  ]
525
551
  existing_refs = {}
526
552
 
527
- with patch(
528
- "unique_toolkit.agentic.tools.a2a.postprocessing.postprocessor.logger"
529
- ) as mock_logger:
530
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
531
-
532
- # Should log once for message 2
533
- mock_logger.debug.assert_called_once()
553
+ loop_response = self._create_mock_loop_response()
554
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
534
555
 
535
556
  # Only valid messages should be processed
536
557
  assert existing_refs == {"source1": 1, "source3": 2}
@@ -542,6 +563,7 @@ class TestConsolidateReferencesInPlace:
542
563
  """Test that responses are processed in sorted sequence number order."""
543
564
  messages = [
544
565
  {
566
+ "name": "Assistant1",
545
567
  "display_name": "Assistant1",
546
568
  "display_config": {"mode": "expanded"},
547
569
  "responses": {
@@ -589,7 +611,8 @@ class TestConsolidateReferencesInPlace:
589
611
  ]
590
612
  existing_refs = {}
591
613
 
592
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
614
+ loop_response = self._create_mock_loop_response()
615
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
593
616
 
594
617
  # Should be processed in order 1, 2, 3 based on response sequence numbers
595
618
  assert existing_refs == {"source1": 1, "source2": 2, "source3": 3}
@@ -601,6 +624,7 @@ class TestConsolidateReferencesInPlace:
601
624
  """Test when source ID already exists in existing_refs."""
602
625
  messages = [
603
626
  {
627
+ "name": "Assistant1",
604
628
  "display_name": "Assistant1",
605
629
  "display_config": {"mode": "expanded"},
606
630
  "responses": {
@@ -622,7 +646,8 @@ class TestConsolidateReferencesInPlace:
622
646
  ]
623
647
  existing_refs = {"existing_source": 99}
624
648
 
625
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
649
+ loop_response = self._create_mock_loop_response()
650
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
626
651
 
627
652
  # Should use existing reference number and not add to new refs
628
653
  assert existing_refs == {"existing_source": 99}
@@ -638,6 +663,7 @@ class TestConsolidateReferencesInPlace:
638
663
  """Test edge case with zero and negative values in existing_refs."""
639
664
  messages = [
640
665
  {
666
+ "name": "Assistant1",
641
667
  "display_name": "Assistant1",
642
668
  "display_config": {"mode": "expanded"},
643
669
  "responses": {
@@ -659,7 +685,8 @@ class TestConsolidateReferencesInPlace:
659
685
  ]
660
686
  existing_refs = {"zero": 0, "negative": -5, "positive": 3}
661
687
 
662
- _consolidate_references_in_place(messages, existing_refs) # type: ignore
688
+ loop_response = self._create_mock_loop_response()
689
+ _consolidate_references_in_place(messages, existing_refs, loop_response) # type: ignore
663
690
 
664
691
  # Should start from max(0, -5, 3) + 1 = 4
665
692
  assert existing_refs["new_source"] == 4
@@ -0,0 +1,46 @@
1
+ REFERENCING_INSTRUCTIONS_FOR_SYSTEM_PROMPT = """
2
+ Whenever you use a fact from a sub-agent response in yours, you MUST always reference it.
3
+
4
+ CRITICAL INSTRUCTION: References must always appear immediately after the fact they support.
5
+ Do NOT collect, group, or move references into a list at the end.
6
+
7
+ Rules:
8
+
9
+ 1. Inline placement: After every fact from SubAgentName, immediately attach its reference(s) inline.
10
+ Example:
11
+ “The stock price of Apple Inc. is $150” <sup><name>SubAgentName 2</name>1</sup>.
12
+
13
+ 2. No separate reference list: Do not place references in footnotes, bibliographies, or at the bottom.
14
+ Wrong:
15
+ “The stock price of Apple Inc. is $150.”
16
+ References: <sup><name>SubAgentName 2</name>1</sup>
17
+ Correct:
18
+ “The stock price of Apple Inc. is $150” <sup><name>SubAgentName 2</name>1</sup>.
19
+
20
+ 3. Exact copy: Copy references character-for-character from SubAgentName’s message.
21
+ Do not alter numbering, labels, or order.
22
+
23
+ 4. Multiple references: If more than one reference supports a single fact, include all of them inline, in the same sentence, in the original order.
24
+ Example:
25
+ “MSFT would be a good investment” <sup><name>SubAgentName 3</name>4</sup><sup><name>SubAgentName 3</name>8</sup>.
26
+ Wrong:
27
+ “MSFT would be a good investment” <sup><name>SubAgentName 3</name>8</sup><sup><name>SubAgentName 3</name>4</sup>. (order changed)
28
+
29
+ 5. Never at the bottom: References must always stay attached inline with the fact.
30
+ Multi-fact Example (Correct):
31
+ “Tesla delivered 400,000 cars in Q2” <sup><name>SubAgentName 4</name>2</sup>.
32
+ “Its revenue for the quarter was $24B” <sup><name>SubAgentName 4</name>5</sup>.
33
+ “The company also expanded its Berlin factory capacity” <sup><name>SubAgentName 4</name>7</sup>.
34
+ Wrong Multi-fact Example:
35
+ “Tesla delivered 400,000 cars in Q2. Its revenue for the quarter was $24B. The company also expanded its Berlin factory capacity.”
36
+ References: <sup><name>SubAgentName 4</name>2</sup><sup><name>SubAgentName 4</name>5</sup><sup><name>SubAgentName 4</name>7</sup>
37
+
38
+ 6. Fact repetition: If you reuse a fact from SubAgentName, you MUST reference it again inline with the correct format.
39
+
40
+ Reminder:
41
+ Inline = directly next to the fact, inside the same sentence or bullet.
42
+ """.strip()
43
+
44
+ REFERENCING_INSTRUCTIONS_FOR_USER_PROMPT = """
45
+ Rememeber to properly reference EACH fact from a sub agent's response with the correct format INLINE.
46
+ """.strip()
@@ -7,10 +7,6 @@ DEFAULT_PARAM_DESCRIPTION_SUB_AGENT_USER_MESSAGE = """
7
7
  This is the message that will be sent to the sub-agent.
8
8
  """.strip()
9
9
 
10
- DEFAULT_FORMAT_INFORMATION_SUB_AGENT_SYSTEM_MESSAGE = """
11
- NEVER mention any references from sub-agent answers in your response.
12
- """.strip()
13
-
14
10
 
15
11
  class SubAgentToolConfig(BaseToolConfig):
16
12
  model_config = get_configuration_dict()
@@ -27,6 +23,10 @@ class SubAgentToolConfig(BaseToolConfig):
27
23
  default=True,
28
24
  description="Whether to reuse the existing chat or create a new one for each sub-agent call.",
29
25
  )
26
+ use_sub_agent_references: bool = Field(
27
+ default=True,
28
+ description="Whether this sub agent's references should be used in the main agent's response.",
29
+ )
30
30
 
31
31
  tool_description_for_system_prompt: str = Field(
32
32
  default="",
@@ -41,7 +41,7 @@ class SubAgentToolConfig(BaseToolConfig):
41
41
  description="Description of the user message parameter that will be sent to the model.",
42
42
  )
43
43
  tool_format_information_for_system_prompt: str = Field(
44
- default=DEFAULT_FORMAT_INFORMATION_SUB_AGENT_SYSTEM_MESSAGE,
44
+ default="",
45
45
  description="Format information that will be included in the system prompt to guide response formatting.",
46
46
  )
47
47
  tool_description_for_user_prompt: str = Field(
@@ -1,5 +1,6 @@
1
1
  import asyncio
2
2
  import contextlib
3
+ import re
3
4
  from typing import Protocol, override
4
5
 
5
6
  import unique_sdk
@@ -79,6 +80,12 @@ class SubAgentTool(Tool[SubAgentToolConfig]):
79
80
  self._sequence_number = 1
80
81
  self._lock = asyncio.Lock()
81
82
 
83
+ @staticmethod
84
+ def get_sub_agent_reference_format(
85
+ name: str, sequence_number: int, reference_number: int
86
+ ) -> str:
87
+ return f"<sup><name>{name} {sequence_number}</name>{reference_number}</sup>"
88
+
82
89
  def subscribe(self, subscriber: SubAgentResponseSubscriber) -> None:
83
90
  self._subscribers.append(subscriber)
84
91
 
@@ -175,6 +182,11 @@ class SubAgentTool(Tool[SubAgentToolConfig]):
175
182
  if response["text"] is None:
176
183
  raise ValueError("No response returned from sub agent")
177
184
 
185
+ response_text_with_references = self._prepare_response_references(
186
+ response=response["text"],
187
+ sequence_number=sequence_number,
188
+ )
189
+
178
190
  await self._notify_progress(
179
191
  tool_call=tool_call,
180
192
  message=tool_input.user_message,
@@ -184,7 +196,7 @@ class SubAgentTool(Tool[SubAgentToolConfig]):
184
196
  return ToolCallResponse(
185
197
  id=tool_call.id, # type: ignore
186
198
  name=tool_call.name,
187
- content=response["text"],
199
+ content=response_text_with_references,
188
200
  )
189
201
 
190
202
  @override
@@ -209,6 +221,21 @@ class SubAgentTool(Tool[SubAgentToolConfig]):
209
221
 
210
222
  return None
211
223
 
224
+ def _prepare_response_references(self, response: str, sequence_number: int) -> str:
225
+ if not self.config.use_sub_agent_references:
226
+ # Remove all references from the response
227
+ response = re.sub(r"<sup>\s*\d+\s*</sup>", "", response)
228
+ return response
229
+
230
+ for ref_number in re.findall(r"<sup>(\d+)</sup>", response):
231
+ reference = self.get_sub_agent_reference_format(
232
+ name=self.name,
233
+ sequence_number=sequence_number,
234
+ reference_number=ref_number,
235
+ )
236
+ response = response.replace(f"<sup>{ref_number}</sup>", reference)
237
+ return response
238
+
212
239
  async def _save_chat_id(self, chat_id: str) -> None:
213
240
  if not self.config.reuse_chat:
214
241
  return
File without changes