Skip to content

Conversation

@monotykamary
Copy link
Contributor

@monotykamary monotykamary commented Apr 30, 2025

This PR implements the Google provider for fast-agent using the native google.genai library and should resolve #6 .

Key changes include:

  • Integration with google.genai.Client for interacting with Google's generative models.
  • Implementation of conversation history conversion between fast-agent's PromptMessageMultipart and google.genai.types.Content.
  • Creation of a GoogleConverter class to handle data structure conversions.
  • Handling of tool calls and responses using the native Google API format.
Normal conversation Tool-use History + tool-use Images
Image 1 Image 2 Image 3 Image 4
Image test code sample
import asyncio
from mcp.types import ImageContent, TextContent
from mcp_agent.core.fastagent import FastAgent
from mcp_agent import RequestParams
from mcp_agent.core.prompt import Prompt
from pathlib import Path

fast = FastAgent("Image test")

@fast.agent(
    name="test",
    model="google.gemini-2.5-flash-preview-04-17",
)

async def main():
    async with fast.run() as agent:
      response: str = await agent.send(
          Prompt.user(
              "Analyze this image",
              Path('/Users/monotykamary/Downloads/dikw.png')
          )
      )

      print(response)

if __name__ == "__main__":
    asyncio.run(main())

This work is a step towards fully leveraging the features of the google.genai library within fast-agent.

@monotykamary monotykamary marked this pull request as draft April 30, 2025 08:03
@monotykamary
Copy link
Contributor Author

monotykamary commented Apr 30, 2025

Test summary
================================= test session starts =================================
platform darwin -- Python 3.12.7, pytest-8.3.5, pluggy-1.5.0 -- /Users/monotykamary/VCS/working-remote/open-source/fast-agent/.venv/bin/python
cachedir: .pytest_cache
rootdir: /Users/monotykamary/VCS/working-remote/open-source/fast-agent
configfile: pyproject.toml
plugins: anyio-4.9.0, asyncio-0.26.0, cov-6.1.1
asyncio: mode=Mode.STRICT, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function
collected 199 items                                                                   

tests/unit/mcp_agent/agents/test_agent_types.py::test_agent_type_default PASSED [  0%]
tests/unit/mcp_agent/agents/workflow/test_orchestrator_agent.py::test_execute_step PASSED [  1%]
tests/unit/mcp_agent/agents/workflow/test_orchestrator_agent.py::test_invalid_agent_handling PASSED [  1%]
tests/unit/mcp_agent/agents/workflow/test_orchestrator_agent.py::test_plan_execution_flow PASSED [  2%]
tests/unit/mcp_agent/agents/workflow/test_orchestrator_agent.py::test_iterative_planning PASSED [  2%]
tests/unit/mcp_agent/agents/workflow/test_router_unit.py::test_routing_response_model PASSED [  3%]
tests/unit/mcp_agent/agents/workflow/test_router_unit.py::test_disallows_empty_agents PASSED [  3%]
tests/unit/mcp_agent/agents/workflow/test_router_unit.py::test_invalid_llm_response PASSED [  4%]
tests/unit/mcp_agent/agents/workflow/test_router_unit.py::test_single_agent_shortcircuit PASSED [  4%]
tests/unit/mcp_agent/core/test_mcp_content.py::test_text_content PASSED         [  5%]
tests/unit/mcp_agent/core/test_mcp_content.py::test_image_content PASSED        [  5%]
tests/unit/mcp_agent/core/test_mcp_content.py::test_resource_content PASSED     [  6%]
tests/unit/mcp_agent/core/test_mcp_content.py::test_prompt_function PASSED      [  6%]
tests/unit/mcp_agent/core/test_mcp_content.py::test_user_assistant_functions PASSED [  7%]
tests/unit/mcp_agent/core/test_prompt.py::test_user_method PASSED               [  7%]
tests/unit/mcp_agent/core/test_prompt.py::test_assistant_method PASSED          [  8%]
tests/unit/mcp_agent/core/test_prompt.py::test_message_method PASSED            [  8%]
tests/unit/mcp_agent/core/test_prompt.py::test_with_file_paths PASSED           [  9%]
tests/unit/mcp_agent/core/test_prompt.py::test_conversation_method PASSED       [  9%]
tests/unit/mcp_agent/core/test_prompt.py::test_from_multipart_method PASSED     [ 10%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_assistant_role_restrictions PASSED [ 10%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_code_file_as_text_document_with_filename PASSED [ 11%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_code_file_as_text_document_with_uri PASSED [ 11%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_embedded_resource_image_url_conversion PASSED [ 12%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_embedded_resource_pdf_conversion PASSED [ 12%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_embedded_resource_pdf_url_conversion PASSED [ 13%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_embedded_resource_text_conversion PASSED [ 13%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_empty_content_list PASSED [ 14%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_image_content_conversion PASSED [ 14%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_mixed_content_with_unsupported_formats PASSED [ 15%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_multiple_content_blocks PASSED [ 15%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_svg_resource_conversion PASSED [ 16%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_text_content_conversion PASSED [ 16%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_unsupported_binary_resource_conversion PASSED [ 17%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicUserConverter::test_unsupported_mime_type_handling PASSED [ 17%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicToolConverter::test_binary_only_tool_result_conversion PASSED [ 18%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicToolConverter::test_create_tool_results_message PASSED [ 18%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicToolConverter::test_empty_tool_result_conversion PASSED [ 19%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicToolConverter::test_error_tool_result_conversion PASSED [ 19%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicToolConverter::test_image_tool_result_conversion PASSED [ 20%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicToolConverter::test_mixed_tool_markdown_result_conversion PASSED [ 20%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicToolConverter::test_mixed_tool_result_conversion PASSED [ 21%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicToolConverter::test_pdf_result_conversion PASSED [ 21%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicToolConverter::test_text_tool_result_conversion PASSED [ 22%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicToolConverter::test_unsupported_image_format_in_tool_result PASSED [ 22%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicAssistantConverter::test_assistant_embedded_resource_stripped PASSED [ 23%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicAssistantConverter::test_assistant_empty_content PASSED [ 23%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicAssistantConverter::test_assistant_multiple_text_blocks PASSED [ 24%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicAssistantConverter::test_assistant_non_text_content_stripped PASSED [ 24%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicAssistantConverter::test_assistant_text_content_conversion PASSED [ 25%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicAssistantConverter::test_convert_prompt_message_embedded_resource_to_anthropic PASSED [ 25%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicAssistantConverter::test_convert_prompt_message_image_to_anthropic PASSED [ 26%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_anthropic.py::TestAnthropicAssistantConverter::test_convert_prompt_message_to_anthropic PASSED [ 26%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIUserConverter::test_code_file_conversion PASSED [ 27%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIUserConverter::test_embedded_resource_image_url_conversion PASSED [ 27%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIUserConverter::test_embedded_resource_pdf_conversion PASSED [ 28%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIUserConverter::test_embedded_resource_text_conversion PASSED [ 28%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIUserConverter::test_empty_content_list PASSED [ 29%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIUserConverter::test_image_content_conversion PASSED [ 29%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIUserConverter::test_multiple_content_blocks PASSED [ 30%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIUserConverter::test_svg_resource_conversion PASSED [ 30%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIUserConverter::test_text_content_conversion PASSED [ 31%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIAssistantConverter::test_assistant_text_content_conversion PASSED [ 31%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIAssistantConverter::test_convert_prompt_message_embedded_resource_to_openai PASSED [ 32%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIAssistantConverter::test_convert_prompt_message_to_openai_assistant PASSED [ 32%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIAssistantConverter::test_convert_prompt_message_to_openai_user_image PASSED [ 33%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIAssistantConverter::test_convert_prompt_message_to_openai_user_text PASSED [ 33%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIAssistantConverter::test_empty_assistant_message PASSED [ 34%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIToolConverter::test_multiple_tool_results_with_mixed_content PASSED [ 34%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIToolConverter::test_tool_result_conversion PASSED [ 35%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestOpenAIToolConverter::test_tool_result_with_mixed_content PASSED [ 35%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestTextConcatenation::test_adjacent_text_blocks_concatenation PASSED [ 36%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestTextConcatenation::test_convert_unsupported_binary_format PASSED [ 36%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestTextConcatenation::test_mixed_content_with_concatenation PASSED [ 37%]
tests/unit/mcp_agent/llm/providers/test_multipart_converter_openai.py::TestTextConcatenation::test_tool_result_with_concatenation PASSED [ 37%]
tests/unit/mcp_agent/llm/providers/test_sampling_converter_anthropic.py::TestAnthropicMCPTypeConverter::test_stop_reason_conversions PASSED [ 38%]
tests/unit/mcp_agent/llm/providers/test_sampling_converter_openai.py::TestOpenAIMCPTypeConverter::test_from_mcp_prompt_message_user PASSED [ 38%]
tests/unit/mcp_agent/llm/providers/test_sampling_converter_openai.py::TestOpenAIMCPTypeConverter::test_from_mcp_prompt_message_assistant PASSED [ 39%]
tests/unit/mcp_agent/llm/test_model_factory.py::test_simple_model_names PASSED  [ 39%]
tests/unit/mcp_agent/llm/test_model_factory.py::test_full_model_strings PASSED  [ 40%]
tests/unit/mcp_agent/llm/test_model_factory.py::test_invalid_inputs PASSED      [ 40%]
tests/unit/mcp_agent/llm/test_model_factory.py::test_llm_class_creation PASSED  [ 41%]
tests/unit/mcp_agent/llm/test_model_factory.py::test_allows_generic_model PASSED [ 41%]
tests/unit/mcp_agent/llm/test_passthrough.py::test_simple_return PASSED         [ 42%]
tests/unit/mcp_agent/llm/test_passthrough.py::test_concatenates_text_for_multiple_parts PASSED [ 42%]
tests/unit/mcp_agent/llm/test_passthrough.py::test_set_fixed_return PASSED      [ 43%]
tests/unit/mcp_agent/llm/test_passthrough.py::test_set_fixed_return_ignores_not_set PASSED [ 43%]
tests/unit/mcp_agent/llm/test_passthrough.py::test_parse_tool_call_no_args PASSED [ 44%]
tests/unit/mcp_agent/llm/test_passthrough.py::test_parse_tool_call_with_args PASSED [ 44%]
tests/unit/mcp_agent/llm/test_passthrough.py::test_generates_structured PASSED  [ 45%]
tests/unit/mcp_agent/llm/test_playback.py::test_model_factory_creates_playback PASSED [ 45%]
tests/unit/mcp_agent/llm/test_playback.py::test_basic_playback_function PASSED  [ 46%]
tests/unit/mcp_agent/llm/test_playback.py::test_simple_playback_functionality PASSED [ 46%]
tests/unit/mcp_agent/llm/test_playback.py::test_exhaustion_behaviour PASSED     [ 47%]
tests/unit/mcp_agent/llm/test_playback.py::test_cannot_load_history_with_structured PASSED [ 47%]
tests/unit/mcp_agent/llm/test_playback.py::test_generates_structured PASSED     [ 48%]
tests/unit/mcp_agent/llm/test_playback.py::test_generates_structured_exhaustion_behaves PASSED [ 48%]
tests/unit/mcp_agent/llm/test_prepare_arguments.py::TestRequestParamsInLLM::test_base_prepare_provider_arguments PASSED [ 49%]
tests/unit/mcp_agent/llm/test_prepare_arguments.py::TestRequestParamsInLLM::test_prepare_arguments_with_exclusions PASSED [ 49%]
tests/unit/mcp_agent/llm/test_prepare_arguments.py::TestRequestParamsInLLM::test_prepare_arguments_with_metadata PASSED [ 50%]
tests/unit/mcp_agent/llm/test_prepare_arguments.py::TestRequestParamsInLLM::test_response_format_handling PASSED [ 50%]
tests/unit/mcp_agent/llm/test_prepare_arguments.py::TestRequestParamsInLLM::test_openai_provider_arguments PASSED [ 51%]
tests/unit/mcp_agent/llm/test_prepare_arguments.py::TestRequestParamsInLLM::test_anthropic_provider_arguments PASSED [ 51%]
tests/unit/mcp_agent/llm/test_prepare_arguments.py::TestRequestParamsInLLM::test_params_dont_overwrite_base_args PASSED [ 52%]
tests/unit/mcp_agent/llm/test_prepare_arguments.py::TestRequestParamsInLLM::test_none_values_not_included PASSED [ 52%]
tests/unit/mcp_agent/llm/test_sampling_converter.py::TestSamplingConverter::test_sampling_message_to_prompt_message_text PASSED [ 53%]
tests/unit/mcp_agent/llm/test_sampling_converter.py::TestSamplingConverter::test_sampling_message_to_prompt_message_image PASSED [ 53%]
tests/unit/mcp_agent/llm/test_sampling_converter.py::TestSamplingConverter::test_convert_messages PASSED [ 54%]
tests/unit/mcp_agent/llm/test_sampling_converter.py::TestSamplingConverter::test_convert_messages_with_mixed_content_types PASSED [ 54%]
tests/unit/mcp_agent/llm/test_sampling_converter.py::TestSamplingConverter::test_extract_request_params_full PASSED [ 55%]
tests/unit/mcp_agent/llm/test_sampling_converter.py::TestSamplingConverter::test_extract_request_params_minimal PASSED [ 55%]
tests/unit/mcp_agent/llm/test_sampling_converter.py::TestSamplingConverter::test_error_result PASSED [ 56%]
tests/unit/mcp_agent/llm/test_sampling_converter.py::TestSamplingConverter::test_error_result_no_model PASSED [ 56%]
tests/unit/mcp_agent/llm/test_structured.py::test_direct_pydantic_conversion PASSED [ 57%]
tests/unit/mcp_agent/llm/test_structured.py::test_structured_with_bad_json PASSED [ 57%]
tests/unit/mcp_agent/llm/test_structured.py::test_chat_turn_counting PASSED     [ 58%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_helpers.py::test_get_text PASSED   [ 58%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_helpers.py::test_get_image_data PASSED [ 59%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_helpers.py::test_get_resource_uri PASSED [ 59%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_helpers.py::test_is_text_content PASSED [ 60%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_helpers.py::test_is_image_content PASSED [ 60%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_helpers.py::test_is_resource_content PASSED [ 61%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_helpers.py::test_message_content_with_prompt_message PASSED [ 61%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_helpers.py::test_message_content_with_multipart PASSED [ 62%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_helpers.py::test_text_at_first_position PASSED [ 62%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptContent::test_apply_substitutions_content PASSED [ 63%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptContent::test_apply_substitutions_missing_var PASSED [ 63%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptContent::test_apply_substitutions_with_resources PASSED [ 64%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptTemplate::test_simple_mode PASSED [ 64%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptTemplate::test_delimited_mode PASSED [ 65%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptTemplate::test_custom_delimiters PASSED [ 65%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptTemplate::test_resources_in_template PASSED [ 66%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptTemplate::test_multiple_resources_in_template PASSED [ 66%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptTemplate::test_apply_substitutions PASSED [ 67%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptTemplateLoader::test_load_from_file PASSED [ 67%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptTemplateLoader::test_get_metadata_simple PASSED [ 68%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptTemplateLoader::test_get_metadata_delimited PASSED [ 68%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestPromptTemplateLoader::test_load_template_with_resources PASSED [ 69%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestImageHandling::test_is_image_mime_type PASSED [ 69%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestImageHandling::test_create_image_content PASSED [ 70%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestImageHandling::test_binary_resource_handling PASSED [ 70%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestImageHandling::test_prompt_template_with_image PASSED [ 71%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestImageHandling::test_create_messages_with_image PASSED [ 71%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestImageHandling::test_resource_handling_functions PASSED [ 72%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestIntegration::test_simple_prompt_substitution PASSED [ 72%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestIntegration::test_delimited_prompt_substitution PASSED [ 73%]
tests/unit/mcp_agent/mcp/prompts/test_prompt_template.py::TestIntegration::test_resource_prompt_substitution PASSED [ 73%]
tests/unit/mcp_agent/mcp/prompts/test_template_multipart_integration.py::TestTemplateMultipartIntegration::test_template_to_multipart_conversion PASSED [ 74%]
tests/unit/mcp_agent/mcp/prompts/test_template_multipart_integration.py::TestTemplateMultipartIntegration::test_template_with_substitutions_to_multipart PASSED [ 74%]
tests/unit/mcp_agent/mcp/prompts/test_template_multipart_integration.py::TestTemplateMultipartIntegration::test_multipart_to_template_conversion PASSED [ 75%]
tests/unit/mcp_agent/mcp/prompts/test_template_multipart_integration.py::TestTemplateMultipartIntegration::test_round_trip_conversion PASSED [ 75%]
tests/unit/mcp_agent/mcp/prompts/test_template_multipart_integration.py::TestTemplateMultipartIntegration::test_save_and_load_from_file PASSED [ 76%]
tests/unit/mcp_agent/mcp/prompts/test_template_multipart_integration.py::TestTemplateMultipartIntegration::test_template_loader_integration PASSED [ 76%]
tests/unit/mcp_agent/mcp/test_mime_utils.py::TestMimeUtils::test_guess_mime_type PASSED [ 77%]
tests/unit/mcp_agent/mcp/test_prompt_format_utils.py::TestPromptFormatUtils::test_multipart_with_resources_to_delimited PASSED [ 77%]
tests/unit/mcp_agent/mcp/test_prompt_format_utils.py::TestPromptFormatUtils::test_delimited_with_resources_to_multipart PASSED [ 78%]
tests/unit/mcp_agent/mcp/test_prompt_format_utils.py::TestPromptFormatUtils::test_multiple_resources_in_one_message PASSED [ 78%]
tests/unit/mcp_agent/mcp/test_prompt_format_utils.py::TestPromptFormatUtils::test_image_handling PASSED [ 79%]
tests/unit/mcp_agent/mcp/test_prompt_format_utils.py::TestPromptFormatUtils::test_save_and_load_with_resources PASSED [ 79%]
tests/unit/mcp_agent/mcp/test_prompt_format_utils.py::TestPromptFormatUtils::test_round_trip_with_mime_types PASSED [ 80%]
tests/unit/mcp_agent/mcp/test_prompt_message_multipart.py::TestPromptMessageMultipart::test_from_prompt_messages_with_single_role PASSED [ 80%]
tests/unit/mcp_agent/mcp/test_prompt_message_multipart.py::TestPromptMessageMultipart::test_from_prompt_messages_with_multiple_roles PASSED [ 81%]
tests/unit/mcp_agent/mcp/test_prompt_message_multipart.py::TestPromptMessageMultipart::test_from_prompt_messages_with_mixed_content_types PASSED [ 81%]
tests/unit/mcp_agent/mcp/test_prompt_message_multipart.py::TestPromptMessageMultipart::test_to_prompt_messages PASSED [ 82%]
tests/unit/mcp_agent/mcp/test_prompt_message_multipart.py::TestPromptMessageMultipart::test_parse_get_prompt_result PASSED [ 82%]
tests/unit/mcp_agent/mcp/test_prompt_message_multipart.py::TestPromptMessageMultipart::test_empty_messages PASSED [ 83%]
tests/unit/mcp_agent/mcp/test_prompt_message_multipart.py::TestPromptMessageMultipart::test_round_trip_conversion PASSED [ 83%]
tests/unit/mcp_agent/mcp/test_prompt_message_multipart.py::TestPromptMessageMultipart::test_from_get_prompt_result PASSED [ 84%]
tests/unit/mcp_agent/mcp/test_prompt_message_multipart.py::TestPromptMessageMultipart::test_getting_last_text_empty PASSED [ 84%]
tests/unit/mcp_agent/mcp/test_prompt_message_multipart.py::TestPromptMessageMultipart::test_convenience_add_text PASSED [ 85%]
tests/unit/mcp_agent/mcp/test_prompt_multipart.py::test_create_messages_with_resources_alternating_roles PASSED [ 85%]
tests/unit/mcp_agent/mcp/test_prompt_multipart.py::test_create_messages_with_resources_roles_with_resources PASSED [ 86%]
tests/unit/mcp_agent/mcp/test_prompt_multipart.py::test_load_prompt_from_file PASSED [ 86%]
tests/unit/mcp_agent/mcp/test_prompt_multipart_conversion.py::test_resource_message_role_merging PASSED [ 87%]
tests/unit/mcp_agent/mcp/test_prompt_multipart_conversion.py::test_alternating_roles_with_no_resources PASSED [ 87%]
tests/unit/mcp_agent/mcp/test_prompt_multipart_conversion.py::test_playback_pattern_with_simple_messages PASSED [ 88%]
tests/unit/mcp_agent/mcp/test_prompt_render.py::TestPromptRender::test_render_text_only_message PASSED [ 88%]
tests/unit/mcp_agent/mcp/test_prompt_render.py::TestPromptRender::test_render_multiple_text_contents PASSED [ 89%]
tests/unit/mcp_agent/mcp/test_prompt_render.py::TestPromptRender::test_render_with_image_content PASSED [ 89%]
tests/unit/mcp_agent/mcp/test_prompt_render.py::TestPromptRender::test_render_with_embedded_text_resource PASSED [ 90%]
tests/unit/mcp_agent/mcp/test_prompt_render.py::TestPromptRender::test_render_with_long_embedded_text_resource PASSED [ 90%]
tests/unit/mcp_agent/mcp/test_prompt_render.py::TestPromptRender::test_render_with_blob_resource PASSED [ 91%]
tests/unit/mcp_agent/mcp/test_prompt_serialization.py::TestPromptSerialization::test_json_serialization_and_deserialization PASSED [ 91%]
tests/unit/mcp_agent/mcp/test_prompt_serialization.py::TestPromptSerialization::test_multipart_to_delimited_format PASSED [ 92%]
tests/unit/mcp_agent/mcp/test_prompt_serialization.py::TestPromptSerialization::test_multipart_with_resources_to_delimited_format PASSED [ 92%]
tests/unit/mcp_agent/mcp/test_prompt_serialization.py::TestPromptSerialization::test_multi_role_messages_to_delimited_format PASSED [ 93%]
tests/unit/mcp_agent/mcp/test_resource_utils.py::TestUriNormalization::test_absolute_path PASSED [ 93%]
tests/unit/mcp_agent/mcp/test_resource_utils.py::TestUriNormalization::test_already_valid_uri PASSED [ 94%]
tests/unit/mcp_agent/mcp/test_resource_utils.py::TestUriNormalization::test_empty_string PASSED [ 94%]
tests/unit/mcp_agent/mcp/test_resource_utils.py::TestUriNormalization::test_file_uri PASSED [ 95%]
tests/unit/mcp_agent/mcp/test_resource_utils.py::TestUriNormalization::test_normalize_uri PASSED [ 95%]
tests/unit/mcp_agent/mcp/test_resource_utils.py::TestUriNormalization::test_relative_path PASSED [ 96%]
tests/unit/mcp_agent/mcp/test_resource_utils.py::TestUriNormalization::test_simple_filename PASSED [ 96%]
tests/unit/mcp_agent/mcp/test_resource_utils.py::TestUriNormalization::test_uri_extraction_edge_cases PASSED [ 97%]
tests/unit/mcp_agent/mcp/test_resource_utils.py::TestUriNormalization::test_windows_path PASSED [ 97%]
tests/unit/mcp_agent/mcp/test_sampling.py::test_build_sampling_agent_config_with_system_prompt PASSED [ 98%]
tests/unit/mcp_agent/mcp/test_sampling.py::test_build_sampling_agent_config_default PASSED [ 98%]
tests/unit/mcp_agent/mcp/test_sampling.py::test_build_sampling_agent_config_empty_system_prompt PASSED [ 99%]
tests/unit/mcp_agent/mcp_agent/test_event_progress.py::test_event_conversion SKIPPED [100%]

================================== warnings summary ===================================
tests/unit/mcp_agent/llm/test_prepare_arguments.py:12
  /Users/monotykamary/VCS/working-remote/open-source/fast-agent/tests/unit/mcp_agent/llm/test_prepare_arguments.py:12: PytestCollectionWarning: cannot collect test class 'TestLLM' because it has a __init__ constructor (from: tests/unit/mcp_agent/llm/test_prepare_arguments.py)
    class TestLLM(AugmentedLLM):

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
====================== 198 passed, 1 skipped, 1 warning in 1.36s ======================
================================= test session starts =================================
platform darwin -- Python 3.12.7, pytest-8.3.5, pluggy-1.5.0 -- /Users/monotykamary/VCS/working-remote/open-source/fast-agent/.venv/bin/python
cachedir: .pytest_cache
rootdir: /Users/monotykamary/VCS/working-remote/open-source/fast-agent
configfile: pyproject.toml
plugins: anyio-4.9.0, asyncio-0.26.0, cov-6.1.1
asyncio: mode=Mode.STRICT, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function
collected 66 items                                                                    

tests/integration/api/test_api.py::test_agent_api_with_simple_prompt PASSED     [  1%]
tests/integration/api/test_api.py::test_agent_api_with_prompt_messages PASSED   [  3%]
tests/integration/api/test_api.py::test_agent_api_with_basic_playback PASSED    [  4%]
tests/integration/api/test_api.py::test_agent_api_with_default_calls PASSED     [  6%]
tests/integration/api/test_api.py::test_mixed_message_types PASSED              [  7%]
tests/integration/api/test_cli_and_mcp_server.py::test_agent_message_cli PASSED [  9%]
tests/integration/api/test_cli_and_mcp_server.py::test_agent_message_prompt_file PASSED [ 10%]
tests/integration/api/test_cli_and_mcp_server.py::test_agent_message_cli_quiet_flag PASSED [ 12%]
tests/integration/api/test_cli_and_mcp_server.py::test_agent_server_option_stdio PASSED [ 13%]
tests/integration/api/test_cli_and_mcp_server.py::test_agent_server_option_stdio_and_prompt_history PASSED [ 15%]
tests/integration/api/test_cli_and_mcp_server.py::test_agent_server_option_sse PASSED [ 16%]
tests/integration/api/test_describe_a2a.py::test_get_agent_card_and_tools PASSED [ 18%]
tests/integration/api/test_logger_textio.py::test_logger_textio_fileno PASSED   [ 19%]
tests/integration/api/test_logger_textio.py::test_logger_textio_write PASSED    [ 21%]
tests/integration/api/test_logger_textio.py::test_logger_textio_real_process PASSED [ 22%]
tests/integration/api/test_logger_textio.py::test_get_stderr_handler PASSED     [ 24%]
tests/integration/api/test_prompt_commands.py::test_command_handling_for_prompts PASSED [ 25%]
tests/integration/api/test_prompt_listing.py::test_get_all_prompts_with_none_server PASSED [ 27%]
tests/integration/api/test_prompt_listing.py::test_apply_prompt_with_namespaced_name PASSED [ 28%]
tests/integration/api/test_provider_keys.py::test_error_for_bad_provider_or_not_set PASSED [ 30%]
tests/integration/api/test_provider_keys.py::test_reads_keys_and_prioritises_config_file PASSED [ 31%]
tests/integration/api/test_provider_keys.py::test_ollama_generic_api_key PASSED [ 33%]
tests/integration/prompt-server/test_prompt_server_integration.py::test_no_delimiters PASSED [ 34%]
tests/integration/prompt-server/test_prompt_server_integration.py::test_no_delimiters_with_variables PASSED [ 36%]
tests/integration/prompt-server/test_prompt_server_integration.py::test_multiturn PASSED [ 37%]
tests/integration/prompt-server/test_prompt_server_integration.py::test_multiturn_with_subsitition PASSED [ 39%]
tests/integration/prompt-server/test_prompt_server_integration.py::test_agent_interface_returns_prompts_list PASSED [ 40%]
tests/integration/prompt-server/test_prompt_server_integration.py::test_get_prompt_with_server_param PASSED [ 42%]
tests/integration/prompt-server/test_prompt_server_integration.py::test_apply_prompt_with_server_param PASSED [ 43%]
tests/integration/prompt-server/test_prompt_server_integration.py::test_handling_multipart_json_format PASSED [ 45%]
tests/integration/prompt-state/test_load_prompt_templates.py::test_load_simple_conversation_from_file PASSED [ 46%]
tests/integration/prompt-state/test_load_prompt_templates.py::test_load_conversation_with_attachments PASSED [ 48%]
tests/integration/prompt-state/test_load_prompt_templates.py::test_save_state_to_simple_text_file PASSED [ 50%]
tests/integration/prompt-state/test_load_prompt_templates.py::test_save_state_to_mcp_json_format PASSED [ 51%]
tests/integration/prompt-state/test_load_prompt_templates.py::test_round_trip_json_attachments PASSED [ 53%]
tests/integration/resources/test_resource_api.py::test_get_resource_with_explicit_server PASSED [ 54%]
tests/integration/resources/test_resource_api.py::test_get_resource_with_auto_server PASSED [ 56%]
tests/integration/resources/test_resource_api.py::test_list_resources PASSED    [ 57%]
tests/integration/resources/test_resource_api.py::test_error_handling PASSED    [ 59%]
tests/integration/resources/test_resource_api.py::test_with_resource_api PASSED [ 60%]
tests/integration/roots/test_roots.py::test_roots_returned PASSED               [ 62%]
tests/integration/sampling/test_sampling_integration.py::test_sampling_feature PASSED [ 63%]
tests/integration/sampling/test_sampling_integration.py::test_sampling_config PASSED [ 65%]
tests/integration/sampling/test_sampling_integration.py::test_sampling_passback PASSED [ 66%]
tests/integration/sampling/test_sampling_integration.py::test_sampling_multi_message_passback PASSED [ 68%]
tests/integration/workflow/chain/test_chain.py::test_disallows_empty_sequence PASSED [ 69%]
tests/integration/workflow/chain/test_chain.py::test_simple_chain PASSED        [ 71%]
tests/integration/workflow/chain/test_chain.py::test_cumulative_chain PASSED    [ 72%]
tests/integration/workflow/chain/test_chain.py::test_chain_functionality PASSED [ 74%]
tests/integration/workflow/chain/test_chain_passthrough.py::test_chain_passthrough PASSED [ 75%]
tests/integration/workflow/evaluator_optimizer/test_evaluator_optimizer.py::test_single_refinement_cycle PASSED [ 77%]
tests/integration/workflow/evaluator_optimizer/test_evaluator_optimizer.py::test_max_refinements_limit PASSED [ 78%]
tests/integration/workflow/evaluator_optimizer/test_evaluator_optimizer.py::test_early_stop_on_quality PASSED [ 80%]
tests/integration/workflow/evaluator_optimizer/test_evaluator_optimizer.py::test_structured_output PASSED [ 81%]
tests/integration/workflow/mixed/test_mixed_workflow.py::test_chaining_routers PASSED [ 83%]
tests/integration/workflow/mixed/test_mixed_workflow.py::test_router_selects_parallel PASSED [ 84%]
tests/integration/workflow/mixed/test_mixed_workflow.py::test_chain_in_eval_optimizer PASSED [ 86%]
tests/integration/workflow/orchestrator/test_orchestrator.py::test_full_plan_execution PASSED [ 87%]
tests/integration/workflow/orchestrator/test_orchestrator.py::test_iterative_plan_execution PASSED [ 89%]
tests/integration/workflow/orchestrator/test_orchestrator.py::test_invalid_agent_handling PASSED [ 90%]
tests/integration/workflow/orchestrator/test_orchestrator.py::test_max_iterations_handling PASSED [ 92%]
tests/integration/workflow/parallel/test_parallel_agent.py::test_parallel_run PASSED [ 93%]
tests/integration/workflow/parallel/test_parallel_agent.py::test_parallel_default_fan_in PASSED [ 95%]
tests/integration/workflow/router/test_router_agent.py::test_router_functionality PASSED [ 96%]
tests/integration/workflow/router/test_router_agent.py::test_router_structured_output PASSED [ 98%]
tests/integration/workflow/router/test_router_agent.py::test_router_invalid_agent_selection PASSED [100%]

================================== warnings summary ===================================
tests/integration/workflow/evaluator_optimizer/test_evaluator_optimizer.py:24
  /Users/monotykamary/VCS/working-remote/open-source/fast-agent/tests/integration/workflow/evaluator_optimizer/test_evaluator_optimizer.py:24: PytestCollectionWarning: cannot collect test class 'TestOutput' because it has a __init__ constructor (from: tests/integration/workflow/evaluator_optimizer/test_evaluator_optimizer.py)
    class TestOutput(BaseModel):

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== 66 passed, 1 warning in 59.02s ============================

@monotykamary monotykamary marked this pull request as ready for review April 30, 2025 09:15
@monotykamary
Copy link
Contributor Author

monotykamary commented Apr 30, 2025

@evalstate I might have botched any semblance of code quality in this PR. Hopefully by moving the Google provider to google.genai, we can do more intricate tricks and support context caching on this side as well.

@evalstate
Copy link
Owner

THANKYOU!!!! I can't wait to play with this - it looks amazing. I'm going to get the other PRs and a couple of defect fixes released in the next day or 2 and then concentrate on bringing this in. I must confess, I did think implementing this would be quite good fun when you got to the different modalities - how has it been so far?

@monotykamary
Copy link
Contributor Author

I must confess, I did think implementing this would be quite good fun when you got to the different modalities - how has it been so far?

Oh don't get your hopes too high; this was an hour and a half work coded with fast-agent (more of super simple coding agent PoC I'm trying to make) and with Cline. The rest is mostly conceptual divide and conquer on Google's admittedly weird schema.

I am pretty confident we've got all of the major features working. The rest will most likely be edge-cases that isn't easily covered by the tests.

@rkunnamp
Copy link

rkunnamp commented May 4, 2025

Sorry for adding a comment not related to the thread here. But couldn't help ask @monotykamary if you could share the coding agent referred here - "super simple coding agent PoC I'm trying to make" . Quite curios to know how fastagent can be leveraged to make coding agents, that perhaps complements other tools out there including "Cline" that you have mentioned.

@evalstate
Copy link
Owner

OK - I've had a chance to take a quick look at this, and seems to be working pretty well.
I've added an alias for gemini2 to make it easier to test with :)

Having a quick look (and the results of the e2e smoke tests), structured outputs don't seem to be returned:
image

There's also something odd happening with Tool Calls (I've not had a chance to investigate), but if you run the chaining.py --model=gemini2 workflow example you get this error:

  File "/home/ssmith/source/fast-agent/src/mcp_agent/llm/providers/augmented_llm_google.py", line 152, in _google_completion
    available_tools = self._converter.convert_to_google_tools(
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ssmith/source/fast-agent/src/mcp_agent/llm/providers/google_converter.py", line 96, in convert_to_google_tools
    parameters=types.Schema(
               ^^^^^^^^^^^^^
  File "/home/ssmith/source/fast-agent/.venv/lib/python3.12/site-packages/pydantic/main.py", line 253, in __init__
    validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 2 validation errors for Schema
properties.max_length.exclusiveMaximum
  Extra inputs are not permitted [type=extra_forbidden, input_value=1000000, input_type=int]
    For further information visit https://errors.pydantic.dev/2.11/v/extra_forbidden
properties.max_length.exclusiveMinimum
  Extra inputs are not permitted [type=extra_forbidden, input_value=0, input_type=int]
    For further information visit https://errors.pydantic.dev/2.11/v/extra_forbidden

So not sure what's happening with that?! There are a few of the multimodal tests failing, but I suspect this issue above is the root cause.

To run the e2e tests (I've added gemini2 to a few of them), for the moment feel free to just comment out the other models where you don't have API keys/access etc.

Below is also some code if you just want an agent that uses structured outputs:

import asyncio
from typing import Annotated, List

from pydantic import BaseModel, Field

from mcp_agent.core.fastagent import FastAgent
from mcp_agent.core.prompt import Prompt
from mcp_agent.core.request_params import RequestParams

# Create the application
fast = FastAgent("fast-agent example")


class FormattedResponse(BaseModel):
    thinking: Annotated[
        str, Field(description="Your reflection on the conversation that is not seen by the user.")
    ]
    message: str


class CityInfo(BaseModel):
    name: str
    country: str
    population: int
    landmarks: List[str]


# Define the agent
@fast.agent(
    name="chat",
    instruction="You are a helpful AI Agent",
#    request_params=(RequestParams(maxTokens=8192)),
)
async def main():
    # use the --model command line switch or agent arguments to change model
    async with fast.run() as agent:
        thinking, response = await agent.chat.structured(
            [Prompt.user("Tell me about London.")],
            CityInfo,
        )


if __name__ == "__main__":
    asyncio.run(main())

Anyway, thank you for the contrib so far - just ping me on here/discord if you need any help/assistance with this :)

@monotykamary
Copy link
Contributor Author

Oh I'll have a quick look 🚀

@monotykamary monotykamary force-pushed the feat/implement-google-genai-provider branch from fca0262 to 4aa8dd1 Compare May 4, 2025 11:56
@monotykamary
Copy link
Contributor Author

Sorry for adding a comment not related to the thread here. But couldn't help ask @monotykamary if you could share the coding agent referred here - "super simple coding agent PoC I'm trying to make" . Quite curios to know how fastagent can be leveraged to make coding agents, that perhaps complements other tools out there including "Cline" that you have mentioned.

@rkunnamp An exercise up to the reader...

I'm kidding, it's really abusing the DesktopCommander MCP and formatting the agents in a way that pass history to each other. One example would be using an infinite loop and pass history whenever /STOP command is passed through the CLI. This would mimic role changes at the system prompt level:

import asyncio
from mcp_agent import RequestParams
from mcp_agent.core.fastagent import FastAgent

...

async def main():
    async with fast.run() as agent:
        while True:
            # Start an interactive session with architect
            await agent.interactive(agent="architect")
            # Pass architect's history to coder for generation
            await agent.coder.generate(agent.architect.message_history)
            # Start an interactive session with coder
            await agent.interactive(agent="coder")
            # Pass architect's history to coder for generation
            await agent.architect.generate(agent.coder.message_history)

if __name__ == "__main__":
    asyncio.run(main())

There are much better patterns that you can use to inject it directly into a following user prompt, instead of updating the system prompt like this to avoid:

  • Killing your prompt cache
  • Role drift due to essentially creating a "few shot" alignment scenario
  • Incorporate flows to do compression or problem distillation before switching agents

Really, the key player here is the MCP server and the agent architecture is up to you. skydeckai-code, or originally called mcp-server-aidd, was probably the first ever of its kind holding all of the tools for MCP-driven AI development.

parallel_tool_calls=False,
systemPrompt=self.instruction, # System instruction will be mapped in _google_completion
parallel_tool_calls=True, # Assume parallel tool calls are supported by default with native API
max_iterations=10,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated default

@evalstate
Copy link
Owner

evalstate commented May 4, 2025

That's great - looks like structured generation is really solid now. And these models are fast through this native interface - really cool :)

I've done another pass of testing and:

  • I've added an alias for gemini2.5; gemini2-flash is not actually great at tool calling... and was causing some issues in my testing. gemini 2.5 seems to fix those.
  • I think PDF should be supported for these models; so it may just be a mime type/conversion thing: https://ai.google.dev/gemini-api/docs/document-processing. I've also been working with @SecretiveShell who is pulling together a supported mime types database we might be able to use....
  • I think I got to the bottom of the ImageContent conversion (I've added a test_multipart_converter_google.py and borrowed a couple of tests from the OpenAI class). I'm not sure of the exact format of "Parts" required for this to work properly though? I made a small change to the handling of text/image content but not sure if it's correct for that API?

Anyway, great stuff so far - think this is a huge enhancement to fast-agent - thanks!

@monotykamary
Copy link
Contributor Author

I did what any sane senior engineer would do on a Monday: merge it and figure it out later 😆

@janspoerer
Copy link
Contributor

This. This is the way.

@evalstate
Copy link
Owner

I got back from the MCP Dev Conference this morning. I've made a couple of tweaks to update to MCP1.9.1 and add aliases for the new Sonnet models. Sounds like this is good to go then, pending a decision on whether we run with this as the default? (And I can see the workflow just failed! :P).

Seems like we are all confident enough to have this as default, and OpenAI as legacy right? One question I have whether the multimodal/tool calling works better/worse via the OpenAI interface. Anyway, would like to get this released in the next version tonight/tomorrow.

@janspoerer
Copy link
Contributor

I think the question is about whether to use OpenAI vs. the native Google genai provider, right? I would propose using the native Google genai provider as the default as there seem to be more features (e.g., PDF) when using the Google genai provider.

@evalstate
Copy link
Owner

Yep - just left a review comment to that effect. Also opens the door to native audio/image generation via this model, and it's faster too. A quick look makes me think the lint failure is the cause of the test failure, but don't have time to dig in right now - not sure which commit broke it! 🫣

@janspoerer
Copy link
Contributor

Ou naughty linter! Glancing at it, this issue is suspiciously close to where I made changes. I’ll check this when I get home.

Not sure if I can change the provider to native Google today though - don’t have that much time. Depends on how involved this change will be.

@evalstate
Copy link
Owner

I think it's just swapping that text at the bottom where I left a comment, might be nice to rename the class but not essential. Not sure I'll be able to release tonight, but will merge/test and go as soon as I once ready.

…_provider_model in -- should resolve the UnboundVariable error that came in tests/unit/mcp_agent/llm/test_model_factory
@janspoerer
Copy link
Contributor

The latest commits address the linting and test issues.

monotykamary#3

9v9brq

@janspoerer
Copy link
Contributor

Understood that only the factory constant needs to be adjusted from GOOGLE to GOOGLE_NATIVE.

The renaming is a good idea as well. Did you mean to rename GOOGLE_NATIVE to GOOGLE? And should we let the OpenAI format in there and call it GOOGLE_OA?

Where did you leave the in-code comments? I cannot see comments in this pull request.

@evalstate
Copy link
Owner

image

Cool, I think we're all done - I'll cut a release of this evening and bring those changes over manually if needed.

@janspoerer
Copy link
Contributor

Got it, thanks.

@monotykamary Plz yolo the PR :-)

@evalstate
Copy link
Owner

quick heads up - i've run out of time to finish this today, but am pushing the release for 1.9.1 so will aim to get this across tomorrow with another little feature i want :)

@hd24-jspoerer
Copy link

Sounds great, thank you. Do let me know if you need help to push this PR through.

@evalstate evalstate merged commit 6706238 into evalstate:main May 29, 2025
5 checks passed
@evalstate
Copy link
Owner

thanks very much both, i've merged that to main with it as the default provider for google 🍾.

only one i can't explain is why PDF doesn't work as part of a tool call, but it's not a blocker (and may well be an API limitation - there are a few edge cases in the Anthropic API around stuff like that).

If I could ask that someone update the docs: https://github.com/evalstate/fast-agent-docs -> I think the rules over the API keys have changed (does it look for both VERTEX and GOOGLE_API_KEY). Also, the old provider is now accessible as "googleoai." and takes api keys in the same way.

thanks again :)

@hd24-jspoerer
Copy link

Thank you very much, I'm very happy that this worked out and will soon try the Google Provider for some of my use cases.

Regarding further help with the documentation.: I'll not be able to get to this week, I think, but will try to put in some time next week.

Here is an issue for this small doc change: #203

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Google Gemini Support

5 participants