qtype 0.1.12__py3-none-any.whl → 0.1.14__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (272) hide show
  1. qtype/` +0 -0
  2. qtype/application/__init__.py +0 -2
  3. qtype/application/converters/tools_from_api.py +28 -22
  4. qtype/application/converters/tools_from_module.py +66 -32
  5. qtype/base/__init__.py +8 -2
  6. qtype/base/logging.py +0 -17
  7. qtype/base/resources.py +193 -0
  8. qtype/cli.py +5 -9
  9. qtype/commands/generate.py +95 -7
  10. qtype/commands/run.py +153 -54
  11. qtype/docs/.pages +8 -0
  12. {docs → qtype/docs}/Concepts/mental-model-and-philosophy.md +1 -1
  13. qtype/docs/Contributing/.pages +4 -0
  14. {docs → qtype/docs}/Contributing/index.md +8 -1
  15. {docs → qtype/docs}/Gallery/dataflow_pipelines.md +18 -4
  16. qtype/docs/Gallery/recipe_chatbot.md +103 -0
  17. qtype/docs/Gallery/recipe_chatbot.mermaid +62 -0
  18. qtype/docs/Gallery/recipe_chatbot.png +0 -0
  19. {docs → qtype/docs}/Gallery/research_assistant.md +4 -5
  20. {docs → qtype/docs}/Gallery/simple_chatbot.md +3 -1
  21. {docs → qtype/docs}/How To/Authentication/configure_aws_authentication.md +2 -2
  22. {docs → qtype/docs}/How To/Authentication/use_api_key_authentication.md +2 -2
  23. {docs → qtype/docs}/How To/Command Line Usage/load_multiple_inputs_from_files.md +24 -9
  24. {docs → qtype/docs}/How To/Command Line Usage/pass_inputs_on_the_cli.md +7 -4
  25. {docs → qtype/docs}/How To/Command Line Usage/serve_with_auto_reload.md +3 -2
  26. {docs → qtype/docs}/How To/Data Processing/adjust_concurrency.md +3 -4
  27. {docs → qtype/docs}/How To/Data Processing/cache_step_results.md +2 -2
  28. {docs → qtype/docs}/How To/Data Processing/decode_json_xml.md +1 -1
  29. {docs → qtype/docs}/How To/Data Processing/explode_collections.md +2 -2
  30. {docs → qtype/docs}/How To/Data Processing/gather_results.md +4 -4
  31. qtype/docs/How To/Data Processing/invoke_other_flows.md +71 -0
  32. qtype/docs/How To/Data Processing/load_data_from_athena.md +49 -0
  33. qtype/docs/How To/Data Processing/load_documents.md +74 -0
  34. qtype/docs/How To/Data Processing/read_data_from_files.md +61 -0
  35. {docs → qtype/docs}/How To/Data Processing/read_sql_databases.md +4 -3
  36. {docs → qtype/docs}/How To/Data Processing/write_data_to_file.md +1 -2
  37. {docs → qtype/docs}/How To/Invoke Models/call_large_language_models.md +1 -1
  38. {docs → qtype/docs}/How To/Invoke Models/create_embeddings.md +1 -1
  39. {docs → qtype/docs}/How To/Invoke Models/reuse_prompts_with_templates.md +2 -3
  40. {docs → qtype/docs}/How To/Language Features/include_raw_text_from_other_files.md +2 -1
  41. {docs → qtype/docs}/How To/Language Features/reference_entities_by_id.md +2 -2
  42. qtype/docs/How To/Language Features/use_agent_skills.md +29 -0
  43. {docs → qtype/docs}/How To/Language Features/use_environment_variables.md +2 -1
  44. qtype/docs/How To/Language Features/use_optional_variables.md +42 -0
  45. {docs → qtype/docs}/How To/Language Features/use_qtype_mcp.md +4 -4
  46. {docs → qtype/docs}/How To/Observability & Debugging/trace_calls_with_open_telemetry.md +1 -1
  47. {docs → qtype/docs}/How To/Observability & Debugging/validate_qtype_yaml.md +3 -2
  48. {docs → qtype/docs}/How To/Observability & Debugging/visualize_application_architecture.md +1 -1
  49. {docs → qtype/docs}/How To/Qtype Server/serve_flows_as_apis.md +3 -3
  50. {docs → qtype/docs}/How To/Qtype Server/serve_flows_as_ui.md +2 -3
  51. {docs → qtype/docs}/How To/Qtype Server/use_conversational_interfaces.md +1 -4
  52. {docs → qtype/docs}/How To/Qtype Server/use_variables_with_ui_hints.md +3 -2
  53. {docs → qtype/docs}/How To/Tools & Integration/bind_tool_inputs_and_outputs.md +1 -2
  54. {docs → qtype/docs}/How To/Tools & Integration/create_tools_from_openapi_specifications.md +10 -14
  55. {docs → qtype/docs}/How To/Tools & Integration/create_tools_from_python_modules.md +5 -8
  56. {docs → qtype/docs}/Reference/cli.md +16 -17
  57. qtype/docs/Tutorials/.pages +1 -0
  58. {docs → qtype/docs}/Tutorials/01-first-qtype-application.md +4 -3
  59. {docs → qtype/docs}/Tutorials/02-conversational-chatbot.md +3 -3
  60. {docs → qtype/docs}/Tutorials/03-structured-data.md +10 -11
  61. {docs → qtype/docs}/Tutorials/04-tools-and-function-calling.md +13 -20
  62. {docs → qtype/docs}/components/APITool.md +1 -1
  63. qtype/docs/components/Aggregate.md +7 -0
  64. qtype/docs/components/Collect.md +6 -0
  65. qtype/docs/components/Construct.md +6 -0
  66. {docs → qtype/docs}/components/DocumentEmbedder.md +0 -1
  67. {docs → qtype/docs}/components/DocumentSplitter.md +0 -1
  68. qtype/docs/components/Explode.md +5 -0
  69. {docs → qtype/docs}/components/FieldExtractor.md +2 -1
  70. qtype/docs/components/InvokeFlow.md +8 -0
  71. qtype/docs/components/InvokeTool.md +8 -0
  72. {docs → qtype/docs}/components/PrimitiveTypeEnum.md +0 -1
  73. {docs → qtype/docs}/components/Source.md +0 -1
  74. {docs → qtype/docs}/components/Step.md +0 -1
  75. {docs → qtype/docs}/components/Tool.md +2 -2
  76. {docs → qtype/docs}/components/Variable.md +2 -0
  77. qtype/docs/legacy_how_tos/.pages +6 -0
  78. qtype/docs/skills/architect/SKILL.md +188 -0
  79. qtype/docs/skills/architect/references/cheatsheet.md +198 -0
  80. qtype/docs/skills/architect/references/patterns.md +29 -0
  81. qtype/docs/stylesheets/extra.css +27 -0
  82. qtype/dsl/linker.py +8 -0
  83. qtype/dsl/model.py +177 -84
  84. qtype/examples/conversational_ai/simple_chatbot_with_auth.qtype.yaml +48 -0
  85. qtype/examples/data_processing/athena_query.qtype.yaml +56 -0
  86. qtype/examples/data_processing/batch_inputs.csv +5 -0
  87. qtype/examples/data_processing/create_sample_db.py +129 -0
  88. qtype/examples/data_processing/invoke_other_flows.qtype.yaml +98 -0
  89. qtype/examples/data_processing/load_documents.qtype.yaml +31 -0
  90. qtype/examples/data_processing/reviews.db +0 -0
  91. qtype/examples/data_processing/sample_article.txt +1 -0
  92. qtype/examples/data_processing/sample_documents.jsonl +5 -0
  93. qtype/examples/invoke_models/invoke_embedding_aws.qtype.yaml +45 -0
  94. qtype/examples/language_features/optional_variables.qtype.yaml +32 -0
  95. qtype/examples/language_features/story_prompt.txt +6 -0
  96. qtype/examples/legacy/data/customers.csv +6 -0
  97. qtype/examples/legacy/echo/readme.md +29 -0
  98. qtype/examples/legacy/qtype_plugin_example.py +51 -0
  99. qtype/examples/legacy/sample_data.txt +43 -0
  100. qtype/examples/legacy/vertex/README.md +11 -0
  101. qtype/examples/rag/recipe_chatbot.qtype.yaml +216 -0
  102. qtype/examples/research_assistant/tavily.qtype.yaml +216 -0
  103. {examples → qtype/examples}/tutorials/03_structured_data.qtype.yaml +2 -2
  104. {examples → qtype/examples}/tutorials/04_tools_and_function_calling.qtype.yaml +5 -5
  105. qtype/interpreter/auth/aws.py +94 -17
  106. qtype/interpreter/auth/generic.py +11 -12
  107. qtype/interpreter/base/secrets.py +4 -2
  108. qtype/interpreter/base/stream_emitter.py +19 -13
  109. qtype/interpreter/conversions.py +15 -14
  110. qtype/interpreter/converters.py +142 -26
  111. qtype/interpreter/executors/agent_executor.py +2 -3
  112. qtype/interpreter/executors/aggregate_executor.py +3 -4
  113. qtype/interpreter/executors/bedrock_reranker_executor.py +17 -28
  114. qtype/interpreter/executors/construct_executor.py +15 -15
  115. qtype/interpreter/executors/doc_to_text_executor.py +1 -3
  116. qtype/interpreter/executors/document_embedder_executor.py +1 -12
  117. qtype/interpreter/executors/field_extractor_executor.py +13 -12
  118. qtype/interpreter/executors/file_source_executor.py +18 -31
  119. qtype/interpreter/executors/invoke_embedding_executor.py +24 -37
  120. qtype/interpreter/executors/invoke_flow_executor.py +2 -2
  121. qtype/interpreter/executors/invoke_tool_executor.py +19 -18
  122. qtype/interpreter/executors/llm_inference_executor.py +18 -18
  123. qtype/interpreter/executors/prompt_template_executor.py +1 -3
  124. qtype/interpreter/executors/sql_source_executor.py +6 -2
  125. qtype/interpreter/flow.py +11 -1
  126. qtype/interpreter/tools/function_tool_helper.py +11 -10
  127. qtype/interpreter/types.py +89 -4
  128. qtype/interpreter/typing.py +31 -32
  129. qtype/mcp/server.py +194 -86
  130. {schema → qtype/schema}/qtype.schema.json +77 -79
  131. qtype/semantic/checker.py +19 -0
  132. qtype/semantic/generate.py +3 -6
  133. qtype/semantic/model.py +26 -33
  134. qtype/semantic/resolver.py +7 -0
  135. qtype/semantic/visualize.py +18 -6
  136. {qtype-0.1.12.dist-info → qtype-0.1.14.dist-info}/METADATA +47 -46
  137. qtype-0.1.14.dist-info/RECORD +361 -0
  138. {qtype-0.1.12.dist-info → qtype-0.1.14.dist-info}/WHEEL +1 -2
  139. docs/How To/Data Processing/read_data_from_files.md +0 -35
  140. docs/components/Aggregate.md +0 -8
  141. docs/components/InvokeFlow.md +0 -8
  142. docs/components/InvokeTool.md +0 -8
  143. docs/components/ToolParameter.md +0 -6
  144. examples/research_assistant/tavily.qtype.yaml +0 -289
  145. qtype/application/facade.py +0 -177
  146. qtype-0.1.12.dist-info/RECORD +0 -325
  147. qtype-0.1.12.dist-info/top_level.txt +0 -1
  148. {docs → qtype/docs}/Contributing/roadmap.md +0 -0
  149. {docs → qtype/docs}/Decisions/ADR-001-Chat-vs-Completion-Endpoint-Features.md +0 -0
  150. {docs → qtype/docs}/Gallery/dataflow_pipelines.mermaid +0 -0
  151. {docs → qtype/docs}/Gallery/research_assistant.mermaid +0 -0
  152. {docs → qtype/docs}/Gallery/simple_chatbot.mermaid +0 -0
  153. {docs → qtype/docs}/How To/Language Features/include_qtype_yaml.md +0 -0
  154. {docs → qtype/docs}/How To/Observability & Debugging/visualize_example.mermaid +0 -0
  155. {docs → qtype/docs}/How To/Qtype Server/flow_as_ui.png +0 -0
  156. {docs → qtype/docs}/Reference/plugins.md +0 -0
  157. {docs → qtype/docs}/Reference/semantic-validation-rules.md +0 -0
  158. {docs → qtype/docs}/Tutorials/example_chat.png +0 -0
  159. {docs → qtype/docs}/Tutorials/index.md +0 -0
  160. {docs → qtype/docs}/components/APIKeyAuthProvider.md +0 -0
  161. {docs → qtype/docs}/components/AWSAuthProvider.md +0 -0
  162. {docs → qtype/docs}/components/AWSSecretManager.md +0 -0
  163. {docs → qtype/docs}/components/Agent.md +0 -0
  164. {docs → qtype/docs}/components/AggregateStats.md +0 -0
  165. {docs → qtype/docs}/components/Application.md +0 -0
  166. {docs → qtype/docs}/components/AuthorizationProvider.md +0 -0
  167. {docs → qtype/docs}/components/AuthorizationProviderList.md +0 -0
  168. {docs → qtype/docs}/components/BearerTokenAuthProvider.md +0 -0
  169. {docs → qtype/docs}/components/BedrockReranker.md +0 -0
  170. {docs → qtype/docs}/components/ChatContent.md +0 -0
  171. {docs → qtype/docs}/components/ChatMessage.md +0 -0
  172. {docs → qtype/docs}/components/ConstantPath.md +0 -0
  173. {docs → qtype/docs}/components/CustomType.md +0 -0
  174. {docs → qtype/docs}/components/Decoder.md +0 -0
  175. {docs → qtype/docs}/components/DecoderFormat.md +0 -0
  176. {docs → qtype/docs}/components/DocToTextConverter.md +0 -0
  177. {docs → qtype/docs}/components/Document.md +0 -0
  178. {docs → qtype/docs}/components/DocumentIndex.md +0 -0
  179. {docs → qtype/docs}/components/DocumentSearch.md +0 -0
  180. {docs → qtype/docs}/components/DocumentSource.md +0 -0
  181. {docs → qtype/docs}/components/Echo.md +0 -0
  182. {docs → qtype/docs}/components/Embedding.md +0 -0
  183. {docs → qtype/docs}/components/EmbeddingModel.md +0 -0
  184. {docs → qtype/docs}/components/FileSource.md +0 -0
  185. {docs → qtype/docs}/components/FileWriter.md +0 -0
  186. {docs → qtype/docs}/components/Flow.md +0 -0
  187. {docs → qtype/docs}/components/FlowInterface.md +0 -0
  188. {docs → qtype/docs}/components/Index.md +0 -0
  189. {docs → qtype/docs}/components/IndexUpsert.md +0 -0
  190. {docs → qtype/docs}/components/InvokeEmbedding.md +0 -0
  191. {docs → qtype/docs}/components/LLMInference.md +0 -0
  192. {docs → qtype/docs}/components/ListType.md +0 -0
  193. {docs → qtype/docs}/components/Memory.md +0 -0
  194. {docs → qtype/docs}/components/MessageRole.md +0 -0
  195. {docs → qtype/docs}/components/Model.md +0 -0
  196. {docs → qtype/docs}/components/ModelList.md +0 -0
  197. {docs → qtype/docs}/components/OAuth2AuthProvider.md +0 -0
  198. {docs → qtype/docs}/components/PromptTemplate.md +0 -0
  199. {docs → qtype/docs}/components/PythonFunctionTool.md +0 -0
  200. {docs → qtype/docs}/components/RAGChunk.md +0 -0
  201. {docs → qtype/docs}/components/RAGDocument.md +0 -0
  202. {docs → qtype/docs}/components/RAGSearchResult.md +0 -0
  203. {docs → qtype/docs}/components/Reranker.md +0 -0
  204. {docs → qtype/docs}/components/SQLSource.md +0 -0
  205. {docs → qtype/docs}/components/Search.md +0 -0
  206. {docs → qtype/docs}/components/SearchResult.md +0 -0
  207. {docs → qtype/docs}/components/SecretManager.md +0 -0
  208. {docs → qtype/docs}/components/SecretReference.md +0 -0
  209. {docs → qtype/docs}/components/TelemetrySink.md +0 -0
  210. {docs → qtype/docs}/components/ToolList.md +0 -0
  211. {docs → qtype/docs}/components/TypeList.md +0 -0
  212. {docs → qtype/docs}/components/VariableList.md +0 -0
  213. {docs → qtype/docs}/components/VectorIndex.md +0 -0
  214. {docs → qtype/docs}/components/VectorSearch.md +0 -0
  215. {docs → qtype/docs}/components/VertexAuthProvider.md +0 -0
  216. {docs → qtype/docs}/components/Writer.md +0 -0
  217. {docs → qtype/docs}/example_ui.png +0 -0
  218. {docs → qtype/docs}/index.md +0 -0
  219. {docs → qtype/docs}/legacy_how_tos/Configuration/modular-yaml.md +0 -0
  220. {docs → qtype/docs}/legacy_how_tos/Configuration/phoenix_projects.png +0 -0
  221. {docs → qtype/docs}/legacy_how_tos/Configuration/phoenix_traces.png +0 -0
  222. {docs → qtype/docs}/legacy_how_tos/Configuration/reference-by-id.md +0 -0
  223. {docs → qtype/docs}/legacy_how_tos/Configuration/telemetry-setup.md +0 -0
  224. {docs → qtype/docs}/legacy_how_tos/Data Types/custom-types.md +0 -0
  225. {docs → qtype/docs}/legacy_how_tos/Data Types/domain-types.md +0 -0
  226. {docs → qtype/docs}/legacy_how_tos/Debugging/visualize-apps.md +0 -0
  227. {docs → qtype/docs}/legacy_how_tos/Tools/api-tools.md +0 -0
  228. {docs → qtype/docs}/legacy_how_tos/Tools/python-tools.md +0 -0
  229. {examples → qtype/examples}/authentication/aws_authentication.qtype.yaml +0 -0
  230. {examples → qtype/examples}/conversational_ai/hello_world_chat.qtype.yaml +0 -0
  231. {examples → qtype/examples}/conversational_ai/simple_chatbot.qtype.yaml +0 -0
  232. {examples → qtype/examples}/data_processing/batch_processing.qtype.yaml +0 -0
  233. {examples → qtype/examples}/data_processing/cache_step_results.qtype.yaml +0 -0
  234. {examples → qtype/examples}/data_processing/collect_results.qtype.yaml +0 -0
  235. {examples → qtype/examples}/data_processing/dataflow_pipelines.qtype.yaml +0 -0
  236. {examples → qtype/examples}/data_processing/decode_json.qtype.yaml +0 -0
  237. {examples → qtype/examples}/data_processing/explode_items.qtype.yaml +0 -0
  238. {examples → qtype/examples}/data_processing/read_file.qtype.yaml +0 -0
  239. {examples → qtype/examples}/invoke_models/create_embeddings.qtype.yaml +0 -0
  240. {examples → qtype/examples}/invoke_models/simple_llm_call.qtype.yaml +0 -0
  241. {examples → qtype/examples}/language_features/include_raw.qtype.yaml +0 -0
  242. {examples → qtype/examples}/language_features/ui_hints.qtype.yaml +0 -0
  243. {examples → qtype/examples}/legacy/bedrock/data_analysis_with_telemetry.qtype.yaml +0 -0
  244. {examples → qtype/examples}/legacy/bedrock/hello_world.qtype.yaml +0 -0
  245. {examples → qtype/examples}/legacy/bedrock/hello_world_chat.qtype.yaml +0 -0
  246. {examples → qtype/examples}/legacy/bedrock/hello_world_chat_with_telemetry.qtype.yaml +0 -0
  247. {examples → qtype/examples}/legacy/bedrock/hello_world_chat_with_thinking.qtype.yaml +0 -0
  248. {examples → qtype/examples}/legacy/bedrock/hello_world_completion.qtype.yaml +0 -0
  249. {examples → qtype/examples}/legacy/bedrock/hello_world_completion_with_auth.qtype.yaml +0 -0
  250. {examples → qtype/examples}/legacy/bedrock/simple_agent_chat.qtype.yaml +0 -0
  251. {examples → qtype/examples}/legacy/chat_with_langfuse.qtype.yaml +0 -0
  252. {examples → qtype/examples}/legacy/data_processor.qtype.yaml +0 -0
  253. {examples → qtype/examples}/legacy/echo/debug_example.qtype.yaml +0 -0
  254. {examples → qtype/examples}/legacy/echo/prompt.qtype.yaml +0 -0
  255. {examples → qtype/examples}/legacy/echo/test.qtype.yaml +0 -0
  256. {examples → qtype/examples}/legacy/echo/video.qtype.yaml +0 -0
  257. {examples → qtype/examples}/legacy/field_extractor_example.qtype.yaml +0 -0
  258. {examples → qtype/examples}/legacy/multi_flow_example.qtype.yaml +0 -0
  259. {examples → qtype/examples}/legacy/openai/hello_world_chat.qtype.yaml +0 -0
  260. {examples → qtype/examples}/legacy/openai/hello_world_chat_with_telemetry.qtype.yaml +0 -0
  261. {examples → qtype/examples}/legacy/rag.qtype.yaml +0 -0
  262. {examples → qtype/examples}/legacy/time_utilities.qtype.yaml +0 -0
  263. {examples → qtype/examples}/legacy/vertex/hello_world_chat.qtype.yaml +0 -0
  264. {examples → qtype/examples}/legacy/vertex/hello_world_completion.qtype.yaml +0 -0
  265. {examples → qtype/examples}/legacy/vertex/hello_world_completion_with_auth.qtype.yaml +0 -0
  266. {examples → qtype/examples}/observability_debugging/trace_with_opentelemetry.qtype.yaml +0 -0
  267. {examples → qtype/examples}/research_assistant/research_assistant.qtype.yaml +0 -0
  268. {examples → qtype/examples}/research_assistant/tavily.oas.yaml +0 -0
  269. {examples → qtype/examples}/tutorials/01_hello_world.qtype.yaml +0 -0
  270. {examples → qtype/examples}/tutorials/02_conversational_chat.qtype.yaml +0 -0
  271. {qtype-0.1.12.dist-info → qtype-0.1.14.dist-info}/entry_points.txt +0 -0
  272. {qtype-0.1.12.dist-info → qtype-0.1.14.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,216 @@
1
+ auths:
2
+ - id: tavily-api_bearerauth_token
3
+ token: ${TAVILY-API_BEARER}
4
+ type: bearer_token
5
+ description: Tools created from API specification
6
+ examples/research_assistant/tavily.oas.yaml
7
+ flows: []
8
+ id: tavily-api
9
+ indexes: []
10
+ memories: []
11
+ models: []
12
+ references: []
13
+ tools:
14
+ - auth: tavily-api_bearerauth_token
15
+ description: 'Perform a web search with various filtering and customization options.
16
+ Returns search results with content, URLs, scores, and optional answers. '
17
+ endpoint: https://api.tavily.com/search
18
+ headers: {}
19
+ id: search
20
+ inputs:
21
+ - id: query
22
+ type: text
23
+ - id: search_depth
24
+ type: text?
25
+ - id: topic
26
+ type: text?
27
+ - id: time_range
28
+ type: text?
29
+ - id: start_date
30
+ type: text?
31
+ - id: end_date
32
+ type: text?
33
+ - id: days
34
+ type: int?
35
+ - id: max_results
36
+ type: int?
37
+ - id: include_domains
38
+ type: list[text]?
39
+ - id: exclude_domains
40
+ type: list[text]?
41
+ - id: include_answer
42
+ type: text?
43
+ - id: include_raw_content
44
+ type: text?
45
+ - id: include_images
46
+ type: boolean?
47
+ - id: country
48
+ type: text?
49
+ - id: auto_parameters
50
+ type: boolean?
51
+ - id: include_favicon
52
+ type: boolean?
53
+ method: POST
54
+ name: Search the web
55
+ outputs:
56
+ - id: query
57
+ type: text?
58
+ - id: follow_up_questions
59
+ type: list[text]?
60
+ - id: answer
61
+ type: text?
62
+ - id: images
63
+ type: list[schema_4849029360]?
64
+ - id: results
65
+ type: list[schema_4849029792]?
66
+ - id: response_time
67
+ type: float?
68
+ parameters: []
69
+ type: APITool
70
+ - auth: tavily-api_bearerauth_token
71
+ description: 'Extract and process content from one or more URLs with various formatting
72
+ options. Returns extracted content in text or markdown format. '
73
+ endpoint: https://api.tavily.com/extract
74
+ headers: {}
75
+ id: extract
76
+ inputs:
77
+ - id: urls
78
+ type: list[text]
79
+ - id: include_images
80
+ type: boolean?
81
+ - id: extract_depth
82
+ type: text?
83
+ - id: format
84
+ type: text?
85
+ - id: include_favicon
86
+ type: boolean?
87
+ method: POST
88
+ name: Extract content from URLs
89
+ outputs:
90
+ - id: results
91
+ type: list[schema_4849038576]?
92
+ - id: failed_results
93
+ type: list[schema_4849041168]?
94
+ parameters: []
95
+ type: APITool
96
+ - auth: tavily-api_bearerauth_token
97
+ description: 'Crawl a website starting from a given URL with depth and breadth controls.
98
+ Extract content from discovered pages with various filtering options. '
99
+ endpoint: https://api.tavily.com/crawl
100
+ headers: {}
101
+ id: crawl
102
+ inputs:
103
+ - id: url
104
+ type: text
105
+ - id: max_depth
106
+ type: int?
107
+ - id: max_breadth
108
+ type: int?
109
+ - id: limit
110
+ type: int?
111
+ - id: instructions
112
+ type: text?
113
+ - id: select_paths
114
+ type: list[text]?
115
+ - id: select_domains
116
+ type: list[text]?
117
+ - id: exclude_paths
118
+ type: list[text]?
119
+ - id: exclude_domains
120
+ type: list[text]?
121
+ - id: allow_external
122
+ type: boolean?
123
+ - id: include_images
124
+ type: boolean?
125
+ - id: extract_depth
126
+ type: text?
127
+ - id: format
128
+ type: text?
129
+ - id: include_favicon
130
+ type: boolean?
131
+ method: POST
132
+ name: Crawl websites
133
+ outputs:
134
+ - id: results
135
+ type: list[schema_4849520304]?
136
+ parameters: []
137
+ type: APITool
138
+ - auth: tavily-api_bearerauth_token
139
+ description: "Map the structure and links of a website starting from a given URL.
140
+ Discover the website's architecture and page hierarchy. "
141
+ endpoint: https://api.tavily.com/map
142
+ headers: {}
143
+ id: map
144
+ inputs:
145
+ - id: url
146
+ type: text
147
+ - id: max_depth
148
+ type: int?
149
+ - id: max_breadth
150
+ type: int?
151
+ - id: limit
152
+ type: int?
153
+ - id: instructions
154
+ type: text?
155
+ - id: select_paths
156
+ type: list[text]?
157
+ - id: select_domains
158
+ type: list[text]?
159
+ - id: exclude_paths
160
+ type: list[text]?
161
+ - id: exclude_domains
162
+ type: list[text]?
163
+ - id: allow_external
164
+ type: boolean?
165
+ - id: include_images
166
+ type: boolean?
167
+ method: POST
168
+ name: Map website structure
169
+ outputs:
170
+ - id: results
171
+ type: list[schema_4849527888]?
172
+ parameters: []
173
+ type: APITool
174
+ types:
175
+ - description: Generated from OpenAPI schema
176
+ id: schema_4849029360
177
+ properties:
178
+ alt_text: text?
179
+ title: text?
180
+ url: text?
181
+ - description: Generated from OpenAPI schema
182
+ id: schema_4849029792
183
+ properties:
184
+ content: text?
185
+ favicon: text?
186
+ raw_content: text?
187
+ score: float?
188
+ title: text?
189
+ url: text?
190
+ - description: Generated from OpenAPI schema
191
+ id: schema_4849038576
192
+ properties:
193
+ content: text?
194
+ favicon: text?
195
+ title: text?
196
+ url: text?
197
+ - description: Generated from OpenAPI schema
198
+ id: schema_4849041168
199
+ properties:
200
+ error: text?
201
+ url: text?
202
+ - description: Generated from OpenAPI schema
203
+ id: schema_4849520304
204
+ properties:
205
+ content: text?
206
+ favicon: text?
207
+ links: list[text]?
208
+ title: text?
209
+ url: text?
210
+ - description: Generated from OpenAPI schema
211
+ id: schema_4849527888
212
+ properties:
213
+ depth: int?
214
+ links: list[text]?
215
+ title: text?
216
+ url: text?
@@ -9,7 +9,7 @@
9
9
  # Scenario: Analyze a product review to extract structured sentiment
10
10
  #
11
11
  # Run with:
12
- # uv run run -i '{"review_text":"These headphones are amazing! Great sound quality and super comfortable. Battery lasts all day."}' examples/tutorials/03_structured_data.qtype.yaml
12
+ # qtype run -i '{"review_text":"These headphones are amazing! Great sound quality and super comfortable. Battery lasts all day."}' examples/tutorials/03_structured_data.qtype.yaml
13
13
 
14
14
  id: review_sentiment_analyzer
15
15
  description: |
@@ -116,7 +116,7 @@ flows:
116
116
  # Construct builds typed objects from the decoded fields
117
117
  - id: build_result
118
118
  type: Construct
119
- field_mapping:
119
+ field_bindings:
120
120
  sentiment: sentiment
121
121
  confidence: confidence
122
122
  key_points: key_points
@@ -8,7 +8,7 @@
8
8
  # Scenario: Calculate a deadline by adding days to the current time
9
9
  #
10
10
  # Run with:
11
- # uv run qtype run -i '{"days_until_due": 3}' examples/tutorials/04_tools_and_function_calling.qtype.yaml
11
+ # qtype run -i '{"days_until_due": 3}' examples/tutorials/04_tools_and_function_calling.qtype.yaml
12
12
 
13
13
  id: deadline_calculator
14
14
  description: |
@@ -17,7 +17,7 @@ description: |
17
17
 
18
18
  # Import pre-built tools from the commons library
19
19
  references:
20
- - !include https://raw.githubusercontent.com/bazaarvoice/qtype/refs/tags/v0.1.11/common/tools.qtype.yaml
20
+ - !include ../../common/tools.qtype.yaml
21
21
 
22
22
  flows:
23
23
  - id: calculate_deadline
@@ -50,7 +50,7 @@ flows:
50
50
  tool: qtype.application.commons.tools.get_current_timestamp
51
51
  input_bindings: {}
52
52
  output_bindings:
53
- result: current_time
53
+ get_current_timestamp_result: current_time
54
54
  outputs:
55
55
  - current_time
56
56
 
@@ -71,7 +71,7 @@ flows:
71
71
  timestamp: current_time
72
72
  days: days_until_due
73
73
  output_bindings:
74
- result: deadline_time
74
+ timedelta_result: deadline_time
75
75
  outputs:
76
76
  - deadline_time
77
77
 
@@ -84,6 +84,6 @@ flows:
84
84
  timestamp: deadline_time
85
85
  format_string: format_string
86
86
  output_bindings:
87
- result: deadline_formatted
87
+ format_datetime_result: deadline_formatted
88
88
  outputs:
89
89
  - deadline_formatted
@@ -8,6 +8,7 @@ AWSAuthProvider configuration from the semantic model.
8
8
  from __future__ import annotations
9
9
 
10
10
  from contextlib import contextmanager
11
+ from dataclasses import asdict, dataclass
11
12
  from typing import Any, Generator
12
13
 
13
14
  import boto3 # type: ignore[import-untyped]
@@ -27,6 +28,30 @@ class AWSAuthenticationError(Exception):
27
28
  pass
28
29
 
29
30
 
31
+ @dataclass
32
+ class AWSCredentials:
33
+ """Resolved AWS credentials for creating boto3/aioboto3 clients.
34
+
35
+ This dataclass holds the resolved AWS credentials that can be passed
36
+ directly to both boto3 and aioboto3 constructors, ensuring async
37
+ operations work correctly without botocore session issues.
38
+ """
39
+
40
+ aws_access_key_id: str | None = None
41
+ aws_secret_access_key: str | None = None
42
+ aws_session_token: str | None = None
43
+ region_name: str | None = None
44
+ profile_name: str | None = None
45
+
46
+ def as_kwargs(self) -> dict[str, Any]:
47
+ """Return non-None credentials as kwargs dict.
48
+
49
+ Returns:
50
+ Dictionary of credential parameters with None values filtered out.
51
+ """
52
+ return {k: v for k, v in asdict(self).items() if v is not None}
53
+
54
+
30
55
  def _is_session_valid(session: boto3.Session) -> bool:
31
56
  """
32
57
  Check if a boto3 session is still valid by testing credential access.
@@ -60,14 +85,18 @@ def _is_session_valid(session: boto3.Session) -> bool:
60
85
  def aws(
61
86
  aws_provider: AWSAuthProvider,
62
87
  secret_manager: SecretManagerBase,
63
- ) -> Generator[boto3.Session, None, None]:
88
+ ) -> Generator[AWSCredentials, None, None]:
64
89
  """
65
- Create a boto3 Session using AWS authentication provider configuration.
90
+ Resolve AWS credentials from provider configuration.
91
+
92
+ This context manager resolves AWS credentials based on the authentication
93
+ method specified in the AWSAuthProvider and returns them as an
94
+ AWSCredentials dataclass. The credentials can be passed directly to both
95
+ boto3 and aioboto3 constructors, ensuring async operations work correctly.
66
96
 
67
- This context manager creates a boto3 Session based on the authentication
68
- method specified in the AWSAuthProvider. Sessions are cached using an LRU
69
- cache to avoid recreating them unnecessarily. The cache size can be configured
70
- via the AUTH_CACHE_MAX_SIZE environment variable (default: 128).
97
+ Sessions are cached using an LRU cache to avoid recreating them
98
+ unnecessarily. The cache size can be configured via the AUTH_CACHE_MAX_SIZE
99
+ environment variable (default: 128).
71
100
 
72
101
  It supports:
73
102
  - Direct credentials (access key + secret key + optional session token)
@@ -81,13 +110,17 @@ def aws(
81
110
  - Invalid or expired sessions are evicted and recreated
82
111
 
83
112
  Args:
84
- aws_provider: AWSAuthProvider instance containing authentication configuration
113
+ aws_provider: AWSAuthProvider instance containing authentication
114
+ configuration
115
+ secret_manager: SecretManagerBase for resolving SecretReferences
85
116
 
86
117
  Yields:
87
- boto3.Session: Configured boto3 session ready for creating AWS service clients
118
+ AWSCredentials: Resolved credentials ready for creating AWS service
119
+ clients
88
120
 
89
121
  Raises:
90
- AWSAuthenticationError: When authentication fails or configuration is invalid
122
+ AWSAuthenticationError: When authentication fails or configuration is
123
+ invalid
91
124
 
92
125
  Example:
93
126
  ```python
@@ -102,9 +135,13 @@ def aws(
102
135
  region="us-east-1"
103
136
  )
104
137
 
105
- with aws(aws_auth) as session:
106
- athena_client = session.client("athena")
107
- s3_client = session.client("s3")
138
+ with aws(aws_auth, secret_manager) as creds:
139
+ # Use with boto3
140
+ client = boto3.client("s3", **creds.as_kwargs())
141
+
142
+ # Or with llama-index Bedrock
143
+ from llama_index.llms.bedrock_converse import BedrockConverse
144
+ llm = BedrockConverse(**creds.as_kwargs(), model="...")
108
145
  ```
109
146
  """
110
147
  try:
@@ -112,8 +149,8 @@ def aws(
112
149
  cached_session = get_cached_auth(aws_provider)
113
150
 
114
151
  if cached_session is not None and _is_session_valid(cached_session):
115
- # Cache hit with valid session
116
- yield cached_session
152
+ # Cache hit with valid session - extract credentials from it
153
+ yield _extract_credentials(cached_session, aws_provider)
117
154
  return
118
155
 
119
156
  # Cache miss or invalid session - create new session
@@ -123,13 +160,15 @@ def aws(
123
160
  credentials = session.get_credentials()
124
161
  if credentials is None:
125
162
  raise AWSAuthenticationError(
126
- f"Failed to obtain AWS credentials for provider '{aws_provider.id}'"
163
+ f"Failed to obtain AWS credentials for provider "
164
+ f"'{aws_provider.id}'"
127
165
  )
128
166
 
129
167
  # Cache the valid session using provider object as key
130
168
  cache_auth(aws_provider, session)
131
169
 
132
- yield session
170
+ # Extract and yield credentials
171
+ yield _extract_credentials(session, aws_provider)
133
172
 
134
173
  except (ClientError, NoCredentialsError) as e:
135
174
  raise AWSAuthenticationError(
@@ -137,10 +176,48 @@ def aws(
137
176
  ) from e
138
177
  except Exception as e:
139
178
  raise AWSAuthenticationError(
140
- f"Unexpected error during AWS authentication for provider '{aws_provider.id}': {e}"
179
+ f"Unexpected error during AWS authentication for provider "
180
+ f"'{aws_provider.id}': {e}"
141
181
  ) from e
142
182
 
143
183
 
184
+ def _extract_credentials(
185
+ session: boto3.Session, aws_provider: AWSAuthProvider
186
+ ) -> AWSCredentials:
187
+ """
188
+ Extract credentials from a boto3 Session.
189
+
190
+ This function extracts the actual credential values from a boto3.Session,
191
+ including temporary credentials from role assumption. This allows the
192
+ credentials to be passed directly to boto3/aioboto3 constructors.
193
+
194
+ Args:
195
+ session: The boto3 session to extract credentials from
196
+ aws_provider: AWSAuthProvider for region/profile information
197
+
198
+ Returns:
199
+ AWSCredentials with the extracted credential values
200
+ """
201
+ credentials = session.get_credentials()
202
+
203
+ if credentials is None:
204
+ # No explicit credentials - use profile or environment
205
+ return AWSCredentials(
206
+ profile_name=aws_provider.profile_name,
207
+ region_name=session.region_name or aws_provider.region,
208
+ )
209
+
210
+ # Extract frozen credentials (works for both static and temporary)
211
+ frozen = credentials.get_frozen_credentials()
212
+
213
+ return AWSCredentials(
214
+ aws_access_key_id=frozen.access_key,
215
+ aws_secret_access_key=frozen.secret_key,
216
+ aws_session_token=frozen.token,
217
+ region_name=session.region_name or aws_provider.region,
218
+ )
219
+
220
+
144
221
  def _create_session(
145
222
  aws_provider: AWSAuthProvider,
146
223
  secret_manager: SecretManagerBase,
@@ -44,9 +44,7 @@ from __future__ import annotations
44
44
  from contextlib import contextmanager
45
45
  from typing import Generator
46
46
 
47
- import boto3 # type: ignore[import-untyped]
48
-
49
- from qtype.interpreter.auth.aws import aws
47
+ from qtype.interpreter.auth.aws import AWSCredentials, aws
50
48
  from qtype.interpreter.base.secrets import SecretManagerBase
51
49
  from qtype.semantic.model import (
52
50
  APIKeyAuthProvider,
@@ -111,13 +109,13 @@ def resolve_provider_secrets(
111
109
  def auth(
112
110
  auth_provider: AuthorizationProvider,
113
111
  secret_manager: SecretManagerBase,
114
- ) -> Generator[boto3.Session | AuthorizationProvider, None, None]:
112
+ ) -> Generator[AWSCredentials | AuthorizationProvider, None, None]:
115
113
  """
116
- Create an appropriate session or provider instance based on the auth provider type.
114
+ Create appropriate credentials or provider instance based on auth provider type.
117
115
 
118
116
  This context manager dispatches to the appropriate authentication handler based
119
117
  on the type of AuthorizationProvider:
120
- - AWSAuthProvider: Returns a configured boto3.Session
118
+ - AWSAuthProvider: Returns AWSCredentials with resolved credentials
121
119
  - APIKeyAuthProvider: Returns the provider instance (contains the API key)
122
120
 
123
121
  Args:
@@ -125,7 +123,7 @@ def auth(
125
123
  secret_manager: Secret manager for resolving SecretReferences
126
124
 
127
125
  Yields:
128
- boto3.Session | APIKeyAuthProvider: The appropriate session or provider instance
126
+ AWSCredentials | AuthorizationProvider: The appropriate credentials or provider instance
129
127
 
130
128
  Raises:
131
129
  UnsupportedAuthProviderError: When an unsupported provider type is used
@@ -135,7 +133,7 @@ def auth(
135
133
  from qtype.semantic.model import AWSAuthProvider, APIKeyAuthProvider
136
134
  from qtype.interpreter.auth.generic import auth
137
135
 
138
- # AWS provider - returns boto3.Session
136
+ # AWS provider - returns AWSCredentials
139
137
  aws_auth = AWSAuthProvider(
140
138
  id="my-aws-auth",
141
139
  type="aws",
@@ -144,8 +142,9 @@ def auth(
144
142
  region="us-east-1"
145
143
  )
146
144
 
147
- with auth(aws_auth) as session:
148
- s3_client = session.client("s3")
145
+ with auth(aws_auth, secret_manager) as creds:
146
+ import boto3
147
+ s3_client = boto3.client("s3", **creds.as_kwargs())
149
148
 
150
149
  # API Key provider - returns the provider itself
151
150
  api_auth = APIKeyAuthProvider(
@@ -161,8 +160,8 @@ def auth(
161
160
  """
162
161
  if isinstance(auth_provider, AWSAuthProvider):
163
162
  # Use AWS-specific context manager
164
- with aws(auth_provider, secret_manager) as session:
165
- yield session
163
+ with aws(auth_provider, secret_manager) as creds:
164
+ yield creds
166
165
 
167
166
  elif isinstance(auth_provider, (APIKeyAuthProvider, OAuth2AuthProvider)):
168
167
  # For non-AWS providers, resolve secrets and yield modified copy
@@ -255,10 +255,12 @@ class AWSSecretManager(SecretManagerBase):
255
255
  json.JSONDecodeError: If secret is not valid JSON when key
256
256
  is specified
257
257
  """
258
+ import boto3
259
+
258
260
  from qtype.interpreter.auth.aws import aws
259
261
 
260
- with aws(self.config.auth) as session: # type: ignore
261
- client = session.client("secretsmanager")
262
+ with aws(self.config.auth) as creds: # type: ignore
263
+ client = boto3.client("secretsmanager", **creds.as_kwargs())
262
264
  response = client.get_secret_value(SecretId=secret_ref.secret_name)
263
265
 
264
266
  if "SecretString" not in response:
@@ -121,15 +121,15 @@ class ReasoningStreamContext:
121
121
  """
122
122
  Async context manager for reasoning streaming.
123
123
 
124
- Automatically emits ReasoningStreamStartEvent on entry and
125
- ReasoningStreamEndEvent on exit. Provides delta() method for emitting
126
- reasoning chunks.
124
+ Only emits ReasoningStreamStartEvent on the first delta() call, and only
125
+ emits ReasoningStreamEndEvent if start was sent. This prevents empty
126
+ reasoning streams when models don't provide reasoning data.
127
127
 
128
128
  Example:
129
129
  ```python
130
130
  async with emitter.reasoning_stream("agent-reasoning") as streamer:
131
131
  async for chunk in agent.stream_reasoning():
132
- await streamer.delta(chunk.text)
132
+ await streamer.delta(chunk.text) # Start event on first call
133
133
  ```
134
134
  """
135
135
 
@@ -142,15 +142,10 @@ class ReasoningStreamContext:
142
142
  self.step = step
143
143
  self.stream_id = stream_id
144
144
  self.on_stream_event = on_stream_event
145
+ self._started = False
145
146
 
146
147
  async def __aenter__(self) -> ReasoningStreamContext:
147
- """Emit ReasoningStreamStartEvent when entering context."""
148
- if self.on_stream_event:
149
- await self.on_stream_event(
150
- ReasoningStreamStartEvent(
151
- step=self.step, stream_id=self.stream_id
152
- )
153
- )
148
+ """Enter context without emitting start event."""
154
149
  return self
155
150
 
156
151
  async def __aexit__(
@@ -159,8 +154,8 @@ class ReasoningStreamContext:
159
154
  exc_val: BaseException | None,
160
155
  exc_tb: Any,
161
156
  ) -> bool:
162
- """Emit ReasoningStreamEndEvent when exiting context."""
163
- if self.on_stream_event:
157
+ """Emit ReasoningStreamEndEvent only if stream was started."""
158
+ if self._started and self.on_stream_event:
164
159
  await self.on_stream_event(
165
160
  ReasoningStreamEndEvent(
166
161
  step=self.step, stream_id=self.stream_id
@@ -172,10 +167,21 @@ class ReasoningStreamContext:
172
167
  """
173
168
  Emit a reasoning delta chunk.
174
169
 
170
+ Sends ReasoningStreamStartEvent on first call, then delta events.
171
+
175
172
  Args:
176
173
  text: The incremental reasoning content to append to the stream
177
174
  """
178
175
  if self.on_stream_event:
176
+ # Emit start event on first delta
177
+ if not self._started:
178
+ await self.on_stream_event(
179
+ ReasoningStreamStartEvent(
180
+ step=self.step, stream_id=self.stream_id
181
+ )
182
+ )
183
+ self._started = True
184
+
179
185
  await self.on_stream_event(
180
186
  ReasoningStreamDeltaEvent(
181
187
  step=self.step,
@@ -194,16 +194,15 @@ def to_llm(
194
194
 
195
195
  from qtype.semantic.model import AWSAuthProvider
196
196
 
197
+ creds_kwargs = {}
197
198
  if model.auth:
198
199
  # Type hint for mypy - we know it's AWSAuthProvider for aws-bedrock
199
200
  assert isinstance(model.auth, AWSAuthProvider)
200
- with aws(model.auth, secret_manager) as session:
201
- session = session._session
202
- else:
203
- session = None
201
+ with aws(model.auth, secret_manager) as creds:
202
+ creds_kwargs = creds.as_kwargs()
204
203
 
205
204
  brv: BaseLLM = BedrockConverse(
206
- botocore_session=session,
205
+ **creds_kwargs,
207
206
  model=model.model_id if model.model_id else model.id,
208
207
  system_prompt=system_prompt,
209
208
  **(model.inference_params if model.inference_params else {}),
@@ -314,14 +313,14 @@ def to_embedding_model(
314
313
  BedrockEmbedding,
315
314
  )
316
315
 
317
- session = None
316
+ creds_kwargs = {}
318
317
  if model.auth is not None:
319
318
  assert isinstance(model.auth, AWSAuthProvider)
320
- with aws(model.auth, secret_manager) as session:
321
- session = session._session
319
+ with aws(model.auth, secret_manager) as creds:
320
+ creds_kwargs = creds.as_kwargs()
322
321
 
323
322
  bedrock_embedding: BaseEmbedding = BedrockEmbedding(
324
- botocore_session=session,
323
+ **creds_kwargs,
325
324
  model_name=model.model_id if model.model_id else model.id,
326
325
  max_retries=100,
327
326
  )
@@ -382,10 +381,12 @@ def to_opensearch_client(
382
381
  elif hasattr(index.auth, "type") and index.auth.type == "aws":
383
382
  # Use AWS authentication with boto3 session
384
383
  # Get AWS credentials from auth provider using context manager
385
- with auth(index.auth, secret_manager) as auth_session:
386
- # Type checker doesn't know this is a boto3.Session
387
- # but runtime validation ensures it for AWS auth
388
- credentials = auth_session.get_credentials() # type: ignore
384
+ with auth(index.auth, secret_manager) as creds:
385
+ # Create a boto3 session from credentials to get boto3.Credentials
386
+ import boto3
387
+
388
+ session = boto3.Session(**creds.as_kwargs())
389
+ credentials = session.get_credentials()
389
390
  if credentials is None:
390
391
  raise InterpreterError(
391
392
  f"Failed to obtain AWS credentials for DocumentIndex '{index.id}'"
@@ -394,7 +395,7 @@ def to_opensearch_client(
394
395
  # Use opensearch-py's async AWS auth
395
396
  aws_auth = AWSV4SignerAsyncAuth(
396
397
  credentials,
397
- auth_session.region_name or "us-east-1", # type: ignore
398
+ creds.region_name or "us-east-1",
398
399
  "aoss", # service name for OpenSearch Serverless
399
400
  )
400
401