fast-agent-mcp 0.4.7__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 (261) hide show
  1. fast_agent/__init__.py +183 -0
  2. fast_agent/acp/__init__.py +19 -0
  3. fast_agent/acp/acp_aware_mixin.py +304 -0
  4. fast_agent/acp/acp_context.py +437 -0
  5. fast_agent/acp/content_conversion.py +136 -0
  6. fast_agent/acp/filesystem_runtime.py +427 -0
  7. fast_agent/acp/permission_store.py +269 -0
  8. fast_agent/acp/server/__init__.py +5 -0
  9. fast_agent/acp/server/agent_acp_server.py +1472 -0
  10. fast_agent/acp/slash_commands.py +1050 -0
  11. fast_agent/acp/terminal_runtime.py +408 -0
  12. fast_agent/acp/tool_permission_adapter.py +125 -0
  13. fast_agent/acp/tool_permissions.py +474 -0
  14. fast_agent/acp/tool_progress.py +814 -0
  15. fast_agent/agents/__init__.py +85 -0
  16. fast_agent/agents/agent_types.py +64 -0
  17. fast_agent/agents/llm_agent.py +350 -0
  18. fast_agent/agents/llm_decorator.py +1139 -0
  19. fast_agent/agents/mcp_agent.py +1337 -0
  20. fast_agent/agents/tool_agent.py +271 -0
  21. fast_agent/agents/workflow/agents_as_tools_agent.py +849 -0
  22. fast_agent/agents/workflow/chain_agent.py +212 -0
  23. fast_agent/agents/workflow/evaluator_optimizer.py +380 -0
  24. fast_agent/agents/workflow/iterative_planner.py +652 -0
  25. fast_agent/agents/workflow/maker_agent.py +379 -0
  26. fast_agent/agents/workflow/orchestrator_models.py +218 -0
  27. fast_agent/agents/workflow/orchestrator_prompts.py +248 -0
  28. fast_agent/agents/workflow/parallel_agent.py +250 -0
  29. fast_agent/agents/workflow/router_agent.py +353 -0
  30. fast_agent/cli/__init__.py +0 -0
  31. fast_agent/cli/__main__.py +73 -0
  32. fast_agent/cli/commands/acp.py +159 -0
  33. fast_agent/cli/commands/auth.py +404 -0
  34. fast_agent/cli/commands/check_config.py +783 -0
  35. fast_agent/cli/commands/go.py +514 -0
  36. fast_agent/cli/commands/quickstart.py +557 -0
  37. fast_agent/cli/commands/serve.py +143 -0
  38. fast_agent/cli/commands/server_helpers.py +114 -0
  39. fast_agent/cli/commands/setup.py +174 -0
  40. fast_agent/cli/commands/url_parser.py +190 -0
  41. fast_agent/cli/constants.py +40 -0
  42. fast_agent/cli/main.py +115 -0
  43. fast_agent/cli/terminal.py +24 -0
  44. fast_agent/config.py +798 -0
  45. fast_agent/constants.py +41 -0
  46. fast_agent/context.py +279 -0
  47. fast_agent/context_dependent.py +50 -0
  48. fast_agent/core/__init__.py +92 -0
  49. fast_agent/core/agent_app.py +448 -0
  50. fast_agent/core/core_app.py +137 -0
  51. fast_agent/core/direct_decorators.py +784 -0
  52. fast_agent/core/direct_factory.py +620 -0
  53. fast_agent/core/error_handling.py +27 -0
  54. fast_agent/core/exceptions.py +90 -0
  55. fast_agent/core/executor/__init__.py +0 -0
  56. fast_agent/core/executor/executor.py +280 -0
  57. fast_agent/core/executor/task_registry.py +32 -0
  58. fast_agent/core/executor/workflow_signal.py +324 -0
  59. fast_agent/core/fastagent.py +1186 -0
  60. fast_agent/core/logging/__init__.py +5 -0
  61. fast_agent/core/logging/events.py +138 -0
  62. fast_agent/core/logging/json_serializer.py +164 -0
  63. fast_agent/core/logging/listeners.py +309 -0
  64. fast_agent/core/logging/logger.py +278 -0
  65. fast_agent/core/logging/transport.py +481 -0
  66. fast_agent/core/prompt.py +9 -0
  67. fast_agent/core/prompt_templates.py +183 -0
  68. fast_agent/core/validation.py +326 -0
  69. fast_agent/event_progress.py +62 -0
  70. fast_agent/history/history_exporter.py +49 -0
  71. fast_agent/human_input/__init__.py +47 -0
  72. fast_agent/human_input/elicitation_handler.py +123 -0
  73. fast_agent/human_input/elicitation_state.py +33 -0
  74. fast_agent/human_input/form_elements.py +59 -0
  75. fast_agent/human_input/form_fields.py +256 -0
  76. fast_agent/human_input/simple_form.py +113 -0
  77. fast_agent/human_input/types.py +40 -0
  78. fast_agent/interfaces.py +310 -0
  79. fast_agent/llm/__init__.py +9 -0
  80. fast_agent/llm/cancellation.py +22 -0
  81. fast_agent/llm/fastagent_llm.py +931 -0
  82. fast_agent/llm/internal/passthrough.py +161 -0
  83. fast_agent/llm/internal/playback.py +129 -0
  84. fast_agent/llm/internal/silent.py +41 -0
  85. fast_agent/llm/internal/slow.py +38 -0
  86. fast_agent/llm/memory.py +275 -0
  87. fast_agent/llm/model_database.py +490 -0
  88. fast_agent/llm/model_factory.py +388 -0
  89. fast_agent/llm/model_info.py +102 -0
  90. fast_agent/llm/prompt_utils.py +155 -0
  91. fast_agent/llm/provider/anthropic/anthropic_utils.py +84 -0
  92. fast_agent/llm/provider/anthropic/cache_planner.py +56 -0
  93. fast_agent/llm/provider/anthropic/llm_anthropic.py +796 -0
  94. fast_agent/llm/provider/anthropic/multipart_converter_anthropic.py +462 -0
  95. fast_agent/llm/provider/bedrock/bedrock_utils.py +218 -0
  96. fast_agent/llm/provider/bedrock/llm_bedrock.py +2207 -0
  97. fast_agent/llm/provider/bedrock/multipart_converter_bedrock.py +84 -0
  98. fast_agent/llm/provider/google/google_converter.py +466 -0
  99. fast_agent/llm/provider/google/llm_google_native.py +681 -0
  100. fast_agent/llm/provider/openai/llm_aliyun.py +31 -0
  101. fast_agent/llm/provider/openai/llm_azure.py +143 -0
  102. fast_agent/llm/provider/openai/llm_deepseek.py +76 -0
  103. fast_agent/llm/provider/openai/llm_generic.py +35 -0
  104. fast_agent/llm/provider/openai/llm_google_oai.py +32 -0
  105. fast_agent/llm/provider/openai/llm_groq.py +42 -0
  106. fast_agent/llm/provider/openai/llm_huggingface.py +85 -0
  107. fast_agent/llm/provider/openai/llm_openai.py +1195 -0
  108. fast_agent/llm/provider/openai/llm_openai_compatible.py +138 -0
  109. fast_agent/llm/provider/openai/llm_openrouter.py +45 -0
  110. fast_agent/llm/provider/openai/llm_tensorzero_openai.py +128 -0
  111. fast_agent/llm/provider/openai/llm_xai.py +38 -0
  112. fast_agent/llm/provider/openai/multipart_converter_openai.py +561 -0
  113. fast_agent/llm/provider/openai/openai_multipart.py +169 -0
  114. fast_agent/llm/provider/openai/openai_utils.py +67 -0
  115. fast_agent/llm/provider/openai/responses.py +133 -0
  116. fast_agent/llm/provider_key_manager.py +139 -0
  117. fast_agent/llm/provider_types.py +34 -0
  118. fast_agent/llm/request_params.py +61 -0
  119. fast_agent/llm/sampling_converter.py +98 -0
  120. fast_agent/llm/stream_types.py +9 -0
  121. fast_agent/llm/usage_tracking.py +445 -0
  122. fast_agent/mcp/__init__.py +56 -0
  123. fast_agent/mcp/common.py +26 -0
  124. fast_agent/mcp/elicitation_factory.py +84 -0
  125. fast_agent/mcp/elicitation_handlers.py +164 -0
  126. fast_agent/mcp/gen_client.py +83 -0
  127. fast_agent/mcp/helpers/__init__.py +36 -0
  128. fast_agent/mcp/helpers/content_helpers.py +352 -0
  129. fast_agent/mcp/helpers/server_config_helpers.py +25 -0
  130. fast_agent/mcp/hf_auth.py +147 -0
  131. fast_agent/mcp/interfaces.py +92 -0
  132. fast_agent/mcp/logger_textio.py +108 -0
  133. fast_agent/mcp/mcp_agent_client_session.py +411 -0
  134. fast_agent/mcp/mcp_aggregator.py +2175 -0
  135. fast_agent/mcp/mcp_connection_manager.py +723 -0
  136. fast_agent/mcp/mcp_content.py +262 -0
  137. fast_agent/mcp/mime_utils.py +108 -0
  138. fast_agent/mcp/oauth_client.py +509 -0
  139. fast_agent/mcp/prompt.py +159 -0
  140. fast_agent/mcp/prompt_message_extended.py +155 -0
  141. fast_agent/mcp/prompt_render.py +84 -0
  142. fast_agent/mcp/prompt_serialization.py +580 -0
  143. fast_agent/mcp/prompts/__init__.py +0 -0
  144. fast_agent/mcp/prompts/__main__.py +7 -0
  145. fast_agent/mcp/prompts/prompt_constants.py +18 -0
  146. fast_agent/mcp/prompts/prompt_helpers.py +238 -0
  147. fast_agent/mcp/prompts/prompt_load.py +186 -0
  148. fast_agent/mcp/prompts/prompt_server.py +552 -0
  149. fast_agent/mcp/prompts/prompt_template.py +438 -0
  150. fast_agent/mcp/resource_utils.py +215 -0
  151. fast_agent/mcp/sampling.py +200 -0
  152. fast_agent/mcp/server/__init__.py +4 -0
  153. fast_agent/mcp/server/agent_server.py +613 -0
  154. fast_agent/mcp/skybridge.py +44 -0
  155. fast_agent/mcp/sse_tracking.py +287 -0
  156. fast_agent/mcp/stdio_tracking_simple.py +59 -0
  157. fast_agent/mcp/streamable_http_tracking.py +309 -0
  158. fast_agent/mcp/tool_execution_handler.py +137 -0
  159. fast_agent/mcp/tool_permission_handler.py +88 -0
  160. fast_agent/mcp/transport_tracking.py +634 -0
  161. fast_agent/mcp/types.py +24 -0
  162. fast_agent/mcp/ui_agent.py +48 -0
  163. fast_agent/mcp/ui_mixin.py +209 -0
  164. fast_agent/mcp_server_registry.py +89 -0
  165. fast_agent/py.typed +0 -0
  166. fast_agent/resources/examples/data-analysis/analysis-campaign.py +189 -0
  167. fast_agent/resources/examples/data-analysis/analysis.py +68 -0
  168. fast_agent/resources/examples/data-analysis/fastagent.config.yaml +41 -0
  169. fast_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +1471 -0
  170. fast_agent/resources/examples/mcp/elicitations/elicitation_account_server.py +88 -0
  171. fast_agent/resources/examples/mcp/elicitations/elicitation_forms_server.py +297 -0
  172. fast_agent/resources/examples/mcp/elicitations/elicitation_game_server.py +164 -0
  173. fast_agent/resources/examples/mcp/elicitations/fastagent.config.yaml +35 -0
  174. fast_agent/resources/examples/mcp/elicitations/fastagent.secrets.yaml.example +17 -0
  175. fast_agent/resources/examples/mcp/elicitations/forms_demo.py +107 -0
  176. fast_agent/resources/examples/mcp/elicitations/game_character.py +65 -0
  177. fast_agent/resources/examples/mcp/elicitations/game_character_handler.py +256 -0
  178. fast_agent/resources/examples/mcp/elicitations/tool_call.py +21 -0
  179. fast_agent/resources/examples/mcp/state-transfer/agent_one.py +18 -0
  180. fast_agent/resources/examples/mcp/state-transfer/agent_two.py +18 -0
  181. fast_agent/resources/examples/mcp/state-transfer/fastagent.config.yaml +27 -0
  182. fast_agent/resources/examples/mcp/state-transfer/fastagent.secrets.yaml.example +15 -0
  183. fast_agent/resources/examples/researcher/fastagent.config.yaml +61 -0
  184. fast_agent/resources/examples/researcher/researcher-eval.py +53 -0
  185. fast_agent/resources/examples/researcher/researcher-imp.py +189 -0
  186. fast_agent/resources/examples/researcher/researcher.py +36 -0
  187. fast_agent/resources/examples/tensorzero/.env.sample +2 -0
  188. fast_agent/resources/examples/tensorzero/Makefile +31 -0
  189. fast_agent/resources/examples/tensorzero/README.md +56 -0
  190. fast_agent/resources/examples/tensorzero/agent.py +35 -0
  191. fast_agent/resources/examples/tensorzero/demo_images/clam.jpg +0 -0
  192. fast_agent/resources/examples/tensorzero/demo_images/crab.png +0 -0
  193. fast_agent/resources/examples/tensorzero/demo_images/shrimp.png +0 -0
  194. fast_agent/resources/examples/tensorzero/docker-compose.yml +105 -0
  195. fast_agent/resources/examples/tensorzero/fastagent.config.yaml +19 -0
  196. fast_agent/resources/examples/tensorzero/image_demo.py +67 -0
  197. fast_agent/resources/examples/tensorzero/mcp_server/Dockerfile +25 -0
  198. fast_agent/resources/examples/tensorzero/mcp_server/entrypoint.sh +35 -0
  199. fast_agent/resources/examples/tensorzero/mcp_server/mcp_server.py +31 -0
  200. fast_agent/resources/examples/tensorzero/mcp_server/pyproject.toml +11 -0
  201. fast_agent/resources/examples/tensorzero/simple_agent.py +25 -0
  202. fast_agent/resources/examples/tensorzero/tensorzero_config/system_schema.json +29 -0
  203. fast_agent/resources/examples/tensorzero/tensorzero_config/system_template.minijinja +11 -0
  204. fast_agent/resources/examples/tensorzero/tensorzero_config/tensorzero.toml +35 -0
  205. fast_agent/resources/examples/workflows/agents_as_tools_extended.py +73 -0
  206. fast_agent/resources/examples/workflows/agents_as_tools_simple.py +50 -0
  207. fast_agent/resources/examples/workflows/chaining.py +37 -0
  208. fast_agent/resources/examples/workflows/evaluator.py +77 -0
  209. fast_agent/resources/examples/workflows/fastagent.config.yaml +26 -0
  210. fast_agent/resources/examples/workflows/graded_report.md +89 -0
  211. fast_agent/resources/examples/workflows/human_input.py +28 -0
  212. fast_agent/resources/examples/workflows/maker.py +156 -0
  213. fast_agent/resources/examples/workflows/orchestrator.py +70 -0
  214. fast_agent/resources/examples/workflows/parallel.py +56 -0
  215. fast_agent/resources/examples/workflows/router.py +69 -0
  216. fast_agent/resources/examples/workflows/short_story.md +13 -0
  217. fast_agent/resources/examples/workflows/short_story.txt +19 -0
  218. fast_agent/resources/setup/.gitignore +30 -0
  219. fast_agent/resources/setup/agent.py +28 -0
  220. fast_agent/resources/setup/fastagent.config.yaml +65 -0
  221. fast_agent/resources/setup/fastagent.secrets.yaml.example +38 -0
  222. fast_agent/resources/setup/pyproject.toml.tmpl +23 -0
  223. fast_agent/skills/__init__.py +9 -0
  224. fast_agent/skills/registry.py +235 -0
  225. fast_agent/tools/elicitation.py +369 -0
  226. fast_agent/tools/shell_runtime.py +402 -0
  227. fast_agent/types/__init__.py +59 -0
  228. fast_agent/types/conversation_summary.py +294 -0
  229. fast_agent/types/llm_stop_reason.py +78 -0
  230. fast_agent/types/message_search.py +249 -0
  231. fast_agent/ui/__init__.py +38 -0
  232. fast_agent/ui/console.py +59 -0
  233. fast_agent/ui/console_display.py +1080 -0
  234. fast_agent/ui/elicitation_form.py +946 -0
  235. fast_agent/ui/elicitation_style.py +59 -0
  236. fast_agent/ui/enhanced_prompt.py +1400 -0
  237. fast_agent/ui/history_display.py +734 -0
  238. fast_agent/ui/interactive_prompt.py +1199 -0
  239. fast_agent/ui/markdown_helpers.py +104 -0
  240. fast_agent/ui/markdown_truncator.py +1004 -0
  241. fast_agent/ui/mcp_display.py +857 -0
  242. fast_agent/ui/mcp_ui_utils.py +235 -0
  243. fast_agent/ui/mermaid_utils.py +169 -0
  244. fast_agent/ui/message_primitives.py +50 -0
  245. fast_agent/ui/notification_tracker.py +205 -0
  246. fast_agent/ui/plain_text_truncator.py +68 -0
  247. fast_agent/ui/progress_display.py +10 -0
  248. fast_agent/ui/rich_progress.py +195 -0
  249. fast_agent/ui/streaming.py +774 -0
  250. fast_agent/ui/streaming_buffer.py +449 -0
  251. fast_agent/ui/tool_display.py +422 -0
  252. fast_agent/ui/usage_display.py +204 -0
  253. fast_agent/utils/__init__.py +5 -0
  254. fast_agent/utils/reasoning_stream_parser.py +77 -0
  255. fast_agent/utils/time.py +22 -0
  256. fast_agent/workflow_telemetry.py +261 -0
  257. fast_agent_mcp-0.4.7.dist-info/METADATA +788 -0
  258. fast_agent_mcp-0.4.7.dist-info/RECORD +261 -0
  259. fast_agent_mcp-0.4.7.dist-info/WHEEL +4 -0
  260. fast_agent_mcp-0.4.7.dist-info/entry_points.txt +7 -0
  261. fast_agent_mcp-0.4.7.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,189 @@
1
+ import asyncio
2
+
3
+ from fast_agent import FastAgent
4
+
5
+ agents = FastAgent(name="Enhanced Researcher")
6
+
7
+
8
+ @agents.agent(
9
+ name="ResearchPlanner",
10
+ model="sonnet", # Using a more capable model for planning
11
+ instruction="""
12
+ You are a strategic research planner. Your job is to:
13
+ 1. Break down complex research questions into specific sub-questions
14
+ 2. Identify the key information sources needed to answer each sub-question
15
+ 3. Outline a structured research plan
16
+
17
+ When given a research topic:
18
+ - Analyze what is being asked and identify the core components
19
+ - Define 3-5 specific sub-questions that need to be answered
20
+ - For each sub-question, suggest specific search queries and information sources
21
+ - Prioritize the most important areas to investigate first
22
+ - Include suggestions for data visualization or analysis if appropriate
23
+
24
+ Your output should be a clear, structured research plan that the Researcher can follow.
25
+ """,
26
+ servers=["brave"],
27
+ )
28
+ @agents.agent(
29
+ name="Researcher",
30
+ model="sonnet", # Using a more capable model for deep research
31
+ instruction="""
32
+ You are an expert research assistant with access to multiple resources:
33
+ - Brave Search for initial exploration and discovering sources
34
+ - Website fetching to read and extract information directly from webpages
35
+ - Python interpreter for data analysis and visualization
36
+ - Filesystem tools to save and organize your findings
37
+
38
+ RESEARCH METHODOLOGY:
39
+ 1. First understand the research plan provided
40
+ 2. For each sub-question, use search tools to find multiple relevant sources
41
+ 3. Go beyond surface-level information by:
42
+ - Consulting primary sources when possible
43
+ - Cross-referencing information across multiple sources
44
+ - Using the fetch tool to access complete articles rather than just search snippets
45
+ - Analyzing data with Python when numerical evidence is needed
46
+ - Creating visualizations when they help clarify complex information
47
+
48
+ CRITICAL INFORMATION ASSESSMENT:
49
+ - Evaluate the credibility of each source (consider recency, authority, potential bias)
50
+ - Look for consensus across multiple sources
51
+ - Highlight any contradictions or areas of debate in the research
52
+ - Clearly state limitations in the available information
53
+
54
+ DOCUMENTATION:
55
+ - Save important information, data, and visualizations to files
56
+ - Always create a comprehensive bibliography with links to all sources
57
+ - Include specific citation details (author, date, publication) when available
58
+ - Note which specific information came from which source
59
+
60
+ FINAL RESPONSE:
61
+ - Structure your findings logically with clear headings
62
+ - Synthesize the information rather than just listing facts
63
+ - Directly address each sub-question from the research plan
64
+ - Use data and visualizations to support key points
65
+ - End with a concise executive summary of your findings
66
+ - Include a "Methodology" section explaining how you conducted your research
67
+ """,
68
+ servers=["brave", "interpreter", "filesystem", "fetch"],
69
+ use_history=True,
70
+ )
71
+ @agents.agent(
72
+ name="FactChecker",
73
+ instruction="""
74
+ You are a meticulous fact-checker and critical evaluator of research. Your responsibilities are to:
75
+
76
+ 1. Verify factual claims by cross-checking with authoritative sources
77
+ 2. Identify any unsupported assertions or logical fallacies
78
+ 3. Detect potential biases or limitations in the research methodology
79
+ 4. Ensure proper representation of diverse perspectives on controversial topics
80
+ 5. Evaluate the quality, reliability, and currency of cited sources
81
+
82
+ When reviewing research:
83
+ - Flag any claims that lack sufficient evidence or citation
84
+ - Identify information that seems outdated or contradicts current consensus
85
+ - Check for oversimplifications of complex topics
86
+ - Ensure numerical data and statistics are accurately represented
87
+ - Verify that quotations are accurate and in proper context
88
+ - Look for any gaps in the research or important perspectives that were omitted
89
+
90
+ Your feedback should be specific, actionable, and structured to help improve accuracy and comprehensiveness.
91
+ """,
92
+ servers=["brave", "fetch"],
93
+ )
94
+ @agents.agent(
95
+ name="Evaluator",
96
+ model="sonnet",
97
+ instruction="""
98
+ You are a senior research quality evaluator with expertise in academic and professional research standards.
99
+
100
+ COMPREHENSIVE EVALUATION CRITERIA:
101
+ 1. Research Methodology
102
+ - Has the researcher followed a structured approach?
103
+ - Were appropriate research methods applied?
104
+ - Is there evidence of strategic information gathering?
105
+
106
+ 2. Source Quality & Diversity
107
+ - Are sources authoritative, current, and relevant?
108
+ - Is there appropriate diversity of sources?
109
+ - Were primary sources consulted when appropriate?
110
+
111
+ 3. Information Depth
112
+ - Does the research go beyond surface-level information?
113
+ - Is there evidence of in-depth analysis?
114
+ - Has the researcher explored multiple aspects of the topic?
115
+
116
+ 4. Critical Analysis
117
+ - Has information been critically evaluated rather than simply reported?
118
+ - Are limitations and uncertainties acknowledged?
119
+ - Are multiple perspectives considered on controversial topics?
120
+
121
+ 5. Data & Evidence
122
+ - Is quantitative data properly analyzed and presented?
123
+ - Are visualizations clear, accurate, and informative?
124
+ - Is qualitative information presented with appropriate context?
125
+
126
+ 6. Documentation & Attribution
127
+ - Are all sources properly cited with complete reference information?
128
+ - Is it clear which information came from which source?
129
+ - Is the bibliography comprehensive and well-formatted?
130
+
131
+ 7. Structure & Communication
132
+ - Is the research presented in a logical, well-organized manner?
133
+ - Are findings communicated clearly and precisely?
134
+ - Is the level of technical language appropriate for the intended audience?
135
+
136
+ 8. Alignment with Previous Feedback
137
+ - Has the researcher addressed specific feedback from previous evaluations?
138
+ - Have requested improvements been successfully implemented?
139
+
140
+ For each criterion, provide:
141
+ - A detailed RATING (EXCELLENT, GOOD, FAIR, or POOR)
142
+ - Specific examples from the research that justify your rating
143
+ - Clear, actionable suggestions for improvement
144
+
145
+ Your evaluation should conclude with:
146
+ - An OVERALL RATING that reflects the research quality
147
+ - A concise summary of the research's major strengths
148
+ - A prioritized list of the most important areas for improvement
149
+
150
+ The researcher should be able to understand exactly why they received their rating and what specific steps they can take to improve.
151
+ """,
152
+ )
153
+ @agents.chain(
154
+ name="ResearchProcess",
155
+ sequence=["ResearchPlanner", "Researcher", "FactChecker"],
156
+ instruction="A comprehensive research workflow that plans, executes, and verifies research",
157
+ cumulative=True,
158
+ )
159
+ @agents.evaluator_optimizer(
160
+ generator="ResearchProcess",
161
+ evaluator="Evaluator",
162
+ max_refinements=3,
163
+ min_rating="EXCELLENT",
164
+ name="EnhancedResearcher",
165
+ )
166
+ async def main() -> None:
167
+ async with agents.run() as agent:
168
+ # Start with a warm-up to set expectations and explain the research approach
169
+ await agent.Researcher.send(
170
+ """I'm an enhanced research assistant trained to conduct thorough, evidence-based research.
171
+ I'll approach your question by:
172
+ 1. Creating a structured research plan
173
+ 2. Gathering information from multiple authoritative sources
174
+ 3. Analyzing data and creating visualizations when helpful
175
+ 4. Fact-checking and verifying all information
176
+ 5. Providing a comprehensive, well-documented answer
177
+
178
+ What would you like me to research for you today?"""
179
+ )
180
+
181
+ # Start the main research workflow
182
+ await agent.prompt("EnhancedResearcher")
183
+
184
+ print("\nWould you like to ask follow-up questions to the Researcher? (Type 'STOP' to end)")
185
+ await agent.prompt("Researcher", default_prompt="STOP")
186
+
187
+
188
+ if __name__ == "__main__":
189
+ asyncio.run(main())
@@ -0,0 +1,36 @@
1
+ import asyncio
2
+
3
+ from fast_agent import FastAgent
4
+
5
+ # from rich import print
6
+
7
+ agents = FastAgent(name="Researcher Agent")
8
+
9
+
10
+ @agents.agent(
11
+ "Researcher",
12
+ instruction="""
13
+ You are a research assistant, with access to internet search (via Brave),
14
+ website fetch, a python interpreter (you can install packages with uv) and a filesystem.
15
+ Use the current working directory to save and create files with both the Interpreter and Filesystem tools.
16
+ The interpreter has numpy, pandas, matplotlib and seaborn already installed
17
+ """,
18
+ servers=["brave", "interpreter", "filesystem", "fetch"],
19
+ )
20
+ async def main() -> None:
21
+ research_prompt = """
22
+ Produce an investment report for the company Eutelsat. The final report should be saved in the filesystem in markdown format, and
23
+ contain at least the following:
24
+ 1 - A brief description of the company
25
+ 2 - Current financial position (find data, create and incorporate charts)
26
+ 3 - A PESTLE analysis
27
+ 4 - An investment thesis for the next 3 years. Include both 'buy side' and 'sell side' arguments, and a final
28
+ summary and recommendation.
29
+ Todays date is 15 February 2025. Include the main data sources consulted in presenting the report.""" # noqa: F841
30
+
31
+ async with agents.run() as agent:
32
+ await agent.prompt()
33
+
34
+
35
+ if __name__ == "__main__":
36
+ asyncio.run(main())
@@ -0,0 +1,2 @@
1
+ OPENAI_API_KEY=
2
+ ANTHROPIC_API_KEY=
@@ -0,0 +1,31 @@
1
+ .PHONY: all
2
+
3
+ build:
4
+ docker compose build
5
+
6
+ up:
7
+ docker compose up -d
8
+
9
+ logs:
10
+ docker compose logs -f
11
+
12
+ tensorzero-logs:
13
+ docker compose logs -f gateway
14
+
15
+ mcp-logs:
16
+ docker compose logs -f mcp-server
17
+
18
+ minio-logs:
19
+ docker compose logs -f minio
20
+
21
+ stop:
22
+ docker compose stop
23
+
24
+ agent:
25
+ uv run agent.py --model=tensorzero.test_chat
26
+
27
+ simple-agent:
28
+ uv run simple_agent.py --model=tensorzero.simple_chat
29
+
30
+ image-test:
31
+ uv run image_demo.py
@@ -0,0 +1,56 @@
1
+ # About the tensorzero / fast-agent integration
2
+
3
+ [TensorZero](https://www.tensorzero.com/) is an open source project designed to help LLM application developers rapidly improve their inference calls. Its core features include:
4
+
5
+ - A uniform inference interface to all leading LLM platforms.
6
+ - The ability to dynamic route to different platforms and program failovers.
7
+ - Automated parameter tuning and training
8
+ - Advance templating features for your system prompts
9
+ - Organization of LLM inference data into a Clickhouse DB allowing for sophisticated downstream analytics
10
+ - A bunch of other good stuff is always in development
11
+
12
+ `tensorzero` is powerful heavy, so we provide here a quickstart example that combines the basic components of `fast-agent`, an MCP server, `tensorzero`, and other supporting services into a cohesive whole.
13
+
14
+ ## Quickstart guide
15
+
16
+ - Install `fast-agent` with the `[tensorzero]` dependency e.g. `uv pip install -U fast-agent-mcp[tensorzero]`
17
+ - Build and activate the `uv` `fast-agent` environment
18
+ - Ensure that ports `3000`, `4000`, `8000`, `9000`, and `9001` are unallocated before running this demo.
19
+ - Run `cp .env.sample .env` and then drop in at least one of `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`. Make sure the accounts are funded.
20
+ - `make up`
21
+ - `make agent`
22
+
23
+ The demo test's our implementation's ability to:
24
+
25
+ - Implement the T0 model gateway as an inference backend
26
+ - Implement T0's dynamic templating feature
27
+ - Have in-conversation memory
28
+ - Describe and execute tool calls
29
+ - Remember previous tool calls
30
+
31
+ A version of a conversation to test all of this could be:
32
+
33
+ ```
34
+ Hi.
35
+
36
+ Tell me a poem.
37
+
38
+ Do you have any tools that you can use?
39
+
40
+ Please demonstrate the use of that tool on your last response.
41
+
42
+ Please summarize the conversation so far.
43
+
44
+ What tool calls have you executed in this session, and what were their results?
45
+ ```
46
+
47
+ ## Multimodal support
48
+
49
+ Run `make image-test` to test the gateway's ability to handle base64-encoded image data
50
+
51
+ ## Development notes:
52
+
53
+ - `make stop` will stop the MCP server and the tensorzero server
54
+ - `make tenzorzero-logs` will tail the tensorzero server logs
55
+ - `make mcp-logs` will tail the MCP server logs
56
+ - Generic `make logs` dumps all log output from all services to terminal
@@ -0,0 +1,35 @@
1
+ import asyncio
2
+
3
+ from fast_agent import FastAgent
4
+ from fast_agent.llm.request_params import RequestParams
5
+
6
+ # Explicitly provide the path to the config file in the current directory
7
+ CONFIG_FILE = "fastagent.config.yaml"
8
+ fast = FastAgent("fast-agent example", config_path=CONFIG_FILE, ignore_unknown_args=True)
9
+
10
+ # Define T0 system variables here
11
+ my_t0_system_vars = {
12
+ "TEST_VARIABLE_1": "Roses are red",
13
+ "TEST_VARIABLE_2": "Violets are blue",
14
+ "TEST_VARIABLE_3": "Sugar is sweet",
15
+ "TEST_VARIABLE_4": "Vibe code responsibly 👍",
16
+ }
17
+
18
+
19
+ @fast.agent(
20
+ name="default",
21
+ instruction="""
22
+ You are an agent dedicated to helping developers understand the relationship between TensoZero and fast-agent. If the user makes a request
23
+ that requires you to invoke the test tools, please do so. When you use the tool, describe your rationale for doing so.
24
+ """,
25
+ servers=["tester"],
26
+ request_params=RequestParams(template_vars=my_t0_system_vars),
27
+ )
28
+ async def main():
29
+ async with fast.run() as agent_app: # Get the AgentApp wrapper
30
+ print("\nStarting interactive session with template_vars set via decorator...")
31
+ await agent_app.interactive()
32
+
33
+
34
+ if __name__ == "__main__":
35
+ asyncio.run(main()) # type: ignore
@@ -0,0 +1,105 @@
1
+ # This is a simplified example for learning purposes. Do not use this in production.
2
+ # For production-ready deployments, see: https://www.tensorzero.com/docs/gateway/deployment
3
+
4
+ # Top-level volumes definition
5
+ volumes:
6
+ minio_data: {}
7
+
8
+ services:
9
+ clickhouse:
10
+ image: clickhouse/clickhouse-server:24.12-alpine
11
+ environment:
12
+ CLICKHOUSE_USER: chuser
13
+ CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
14
+ CLICKHOUSE_PASSWORD: chpassword
15
+ ports:
16
+ - "8123:8123"
17
+ healthcheck:
18
+ test: wget --spider --tries 1 http://chuser:chpassword@clickhouse:8123/ping
19
+ start_period: 30s
20
+ start_interval: 1s
21
+ timeout: 1s
22
+
23
+ gateway:
24
+ image: tensorzero/gateway
25
+ volumes:
26
+ - ./tensorzero_config:/app/config:ro
27
+ env_file:
28
+ - ./.env
29
+ command: --config-file /app/config/tensorzero.toml
30
+ environment: # WARNING: Insecure default credentials for local testing ONLY. Don't send this to production.
31
+ TENSORZERO_CLICKHOUSE_URL: http://chuser:chpassword@clickhouse:8123/tensorzero
32
+ S3_ACCESS_KEY_ID: user
33
+ S3_SECRET_ACCESS_KEY: password
34
+ ports:
35
+ - "3000:3000"
36
+ extra_hosts:
37
+ - "host.docker.internal:host-gateway"
38
+ depends_on:
39
+ clickhouse:
40
+ condition: service_healthy
41
+ minio:
42
+ condition: service_healthy
43
+ mcp-server:
44
+ condition: service_healthy
45
+
46
+ gateway-ui:
47
+ image: tensorzero/ui
48
+ volumes:
49
+ - ./tensorzero_config:/app/config:ro
50
+ env_file:
51
+ - ./.env
52
+ command: --config-file /app/config/tensorzero.toml
53
+ environment:
54
+ TENSORZERO_CLICKHOUSE_URL: http://chuser:chpassword@clickhouse:8123/tensorzero
55
+ TENSORZERO_GATEWAY_URL: http://gateway:3000
56
+ S3_ACCESS_KEY_ID: user
57
+ S3_SECRET_ACCESS_KEY: password
58
+ ports:
59
+ - "4000:4000"
60
+ depends_on:
61
+ clickhouse:
62
+ condition: service_healthy
63
+
64
+ mcp-server:
65
+ build:
66
+ context: ./mcp_server
67
+ dockerfile: Dockerfile
68
+ working_dir: /app
69
+ volumes:
70
+ - ./mcp_server:/app
71
+ ports:
72
+ - "8000:8000"
73
+ depends_on:
74
+ minio:
75
+ condition: service_healthy
76
+ healthcheck:
77
+ test:
78
+ [
79
+ "CMD",
80
+ "wget",
81
+ "--spider",
82
+ "--tries=1",
83
+ "http://localhost:8000/t0-example-server/sse",
84
+ ]
85
+ interval: 10s
86
+ timeout: 5s
87
+ retries: 12
88
+ start_period: 20s
89
+
90
+ minio:
91
+ image: minio/minio:latest
92
+ ports:
93
+ - "9000:9000" # API port
94
+ - "9001:9001" # Console port
95
+ volumes:
96
+ - minio_data:/data
97
+ environment: # WARNING: Insecure default credentials for local testing ONLY.
98
+ MINIO_ROOT_USER: user
99
+ MINIO_ROOT_PASSWORD: password
100
+ command: server /data --console-address :9001
101
+ healthcheck:
102
+ test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
103
+ interval: 30s
104
+ timeout: 20s
105
+ retries: 3
@@ -0,0 +1,19 @@
1
+ default_model: haiku
2
+
3
+ tensorzero:
4
+ base_url: http://localhost:3000
5
+ api_key: verysecret
6
+
7
+ logger:
8
+ level: "info"
9
+ progress_display: true
10
+ show_chat: true
11
+ show_tools: true
12
+ truncate_tools: true
13
+
14
+ mcp:
15
+ servers:
16
+ tester:
17
+ transport: "sse"
18
+ url: "http://localhost:8000/t0-example-server/sse"
19
+ read_transport_sse_timeout_seconds: 300
@@ -0,0 +1,67 @@
1
+ import asyncio
2
+ import base64
3
+ import mimetypes
4
+ from pathlib import Path
5
+ from typing import Union
6
+
7
+ from mcp.types import ImageContent, TextContent
8
+
9
+ from fast_agent import FastAgent
10
+ from fast_agent.core.prompt import Prompt
11
+ from fast_agent.llm.request_params import RequestParams
12
+
13
+ AGENT_NAME = "tensorzero_image_tester"
14
+ TENSORZERO_MODEL = "tensorzero.test_chat"
15
+ TEXT_PROMPT = (
16
+ "Provide a description of the similarities and differences between these three images."
17
+ )
18
+ LOCAL_IMAGE_FILES = [
19
+ Path("./demo_images/clam.jpg"),
20
+ Path("./demo_images/shrimp.png"),
21
+ Path("./demo_images/crab.png"),
22
+ ]
23
+
24
+ MY_T0_SYSTEM_VARS = {
25
+ "TEST_VARIABLE_1": "Roses are red",
26
+ "TEST_VARIABLE_2": "Violets are blue",
27
+ "TEST_VARIABLE_3": "Sugar is sweet",
28
+ "TEST_VARIABLE_4": "Vibe code responsibly 👍",
29
+ }
30
+
31
+ fast = FastAgent("TensorZero Image Demo - Base64 Only")
32
+
33
+
34
+ @fast.agent(
35
+ name=AGENT_NAME,
36
+ model=TENSORZERO_MODEL,
37
+ request_params=RequestParams(template_vars=MY_T0_SYSTEM_VARS),
38
+ )
39
+ async def main():
40
+ content_parts: list[Union[TextContent, ImageContent]] = []
41
+ content_parts.append(TextContent(type="text", text=TEXT_PROMPT))
42
+
43
+ for file_path in LOCAL_IMAGE_FILES:
44
+ mime_type, _ = mimetypes.guess_type(file_path)
45
+ if not mime_type or not mime_type.startswith("image/"):
46
+ ext = file_path.suffix.lower()
47
+ if ext == ".jpg" or ext == ".jpeg":
48
+ mime_type = "image/jpeg"
49
+ elif ext == ".png":
50
+ mime_type = "image/png"
51
+ if mime_type is None:
52
+ mime_type = "image/png" # Default fallback if still None
53
+
54
+ with open(file_path, "rb") as image_file:
55
+ image_bytes = image_file.read()
56
+
57
+ encoded_data = base64.b64encode(image_bytes).decode("utf-8")
58
+ content_parts.append(ImageContent(type="image", mimeType=mime_type, data=encoded_data))
59
+
60
+ message = Prompt.user(*content_parts)
61
+ async with fast.run() as agent_app:
62
+ agent = getattr(agent_app, AGENT_NAME)
63
+ await agent.send(message)
64
+
65
+
66
+ if __name__ == "__main__":
67
+ asyncio.run(main()) # type: ignore
@@ -0,0 +1,25 @@
1
+ FROM python:3.12-slim
2
+ WORKDIR /app
3
+
4
+ RUN apt-get update && apt-get install -y curl wget && \
5
+ wget https://dl.min.io/client/mc/release/linux-amd64/mc -O /usr/local/bin/mc && \
6
+ chmod +x /usr/local/bin/mc && \
7
+ apt-get clean && rm -rf /var/lib/apt/lists/*
8
+
9
+ RUN pip install uv
10
+
11
+ # Copy dependency files only
12
+ COPY pyproject.toml /tmp/
13
+ #COPY uv.lock /tmp/
14
+
15
+ # Install dependencies
16
+ WORKDIR /tmp
17
+ RUN uv pip install --system .
18
+
19
+ # Switch back to /app (this will be overridden by volume mount)
20
+ WORKDIR /app
21
+
22
+ # These files will come from the volume mount at runtime
23
+ EXPOSE 8000
24
+ ENTRYPOINT ["/app/entrypoint.sh"]
25
+ CMD ["uvicorn", "mcp_server:app", "--host", "0.0.0.0", "--port", "8000"]
@@ -0,0 +1,35 @@
1
+ #!/bin/sh
2
+
3
+ echo "Entrypoint: Waiting for MinIO to be healthy..."
4
+
5
+ # Simple loop to check MinIO health endpoint (within the Docker network)
6
+ # Adjust timeout as needed
7
+ TIMEOUT=60
8
+ START_TIME=$(date +%s)
9
+ while ! curl -sf http://minio:9000/minio/health/live > /dev/null; do
10
+ CURRENT_TIME=$(date +%s)
11
+ ELAPSED=$(($CURRENT_TIME - $START_TIME))
12
+ if [ $ELAPSED -ge $TIMEOUT ]; then
13
+ echo "Entrypoint: Timeout waiting for MinIO!"
14
+ exit 1
15
+ fi
16
+ echo "Entrypoint: MinIO not ready, sleeping..."
17
+ sleep 2
18
+ done
19
+ echo "Entrypoint: MinIO is healthy."
20
+
21
+ echo "Entrypoint: Configuring mc client and creating bucket 'tensorzero'..."
22
+
23
+ # Configure mc to talk to the MinIO server using the service name
24
+ # Use --insecure because we are using http
25
+ mc --insecure alias set local http://minio:9000 user password
26
+
27
+ # Create the bucket if it doesn't exist
28
+ # Use --insecure because we are using http
29
+ mc --insecure ls local/tensorzero > /dev/null 2>&1 || mc --insecure mb local/tensorzero
30
+
31
+ echo "Entrypoint: Bucket 'tensorzero' check/creation complete."
32
+
33
+ echo "Entrypoint: Executing the main container command: $@"
34
+
35
+ exec "$@"
@@ -0,0 +1,31 @@
1
+ import uvicorn
2
+ from mcp.server.fastmcp.server import FastMCP
3
+ from starlette.applications import Starlette
4
+ from starlette.routing import Mount
5
+
6
+ SERVER_PATH = "t0-example-server"
7
+
8
+
9
+ mcp_instance = FastMCP(name="t0-example-server")
10
+ mcp_instance.settings.message_path = f"/{SERVER_PATH}/messages/"
11
+ mcp_instance.settings.sse_path = f"/{SERVER_PATH}/sse"
12
+
13
+
14
+ @mcp_instance.tool()
15
+ def example_tool(input_text: str) -> str:
16
+ """Example tool that reverses the text of a given string."""
17
+ reversed_text = input_text[::-1]
18
+ return reversed_text
19
+
20
+
21
+ app = Starlette(
22
+ routes=[
23
+ Mount("/", app=mcp_instance.sse_app()),
24
+ ]
25
+ )
26
+
27
+ if __name__ == "__main__":
28
+ print(f"Starting minimal MCP server ({mcp_instance.name}) on http://127.0.0.1:8000")
29
+ print(f" -> SSE endpoint: {mcp_instance.settings.sse_path}")
30
+ print(f" -> Message endpoint: {mcp_instance.settings.message_path}")
31
+ uvicorn.run(app, host="127.0.0.1", port=8000)
@@ -0,0 +1,11 @@
1
+ [project]
2
+ name = "mcp-server"
3
+ version = "0.1.0"
4
+ description = "Add your description here"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = [
8
+ "fastmcp>=2.10.6",
9
+ "starlette>=0.46.2",
10
+ "uvicorn>=0.34.3",
11
+ ]