any-agent

repository·main·Indexed 22 days ago

https://github.com/mozilla-ai/any-agent

A unified interface for using and evaluating different agent frameworks under one API. It supports frameworks including Agno, Google ADK, LangChain, LlamaIndex, OpenAI Agents SDK, smolagents, and TinyAgent. Features include Agent-to-Agent (A2A) protocol support for multi-agent orchestration, local LLM configuration via Ollama, and a callback system for monitoring, rate limiting, and data scrubbing.

Tokens
24.7K
Snippets
77
Records
91
Agent score
78%

What's inside any-agent

  1. Important: any-agent is in soft deprecation

    main

    Deprecation Notice

    any-agent is currently in soft deprecation. It was originally a research project to compare agent frameworks and refine a common surface. This core functionality has moved to a dedicated package: mozilla-ai-tinyagent (PyPI: mozilla-ai-tinyagent).

    When to use any-agent vs tinyagent:

    • Use any-agent if you specifically need to run or evaluate agents across multiple frameworks (such as Agno, Google ADK, LangChain, LlamaIndex, OpenAI Agents SDK, or smolagents) using a single unified API.
    • Use tinyagent for new projects that only require a core agent loop. It is the leaner, recommended path for standard agent development.
  2. Access Agent Traces from agent.run

    main
    When you call agent.run or agent.run_async, the library returns an AgentTrace object. This object contains standardized OpenTelemetry traces based on the Semantic conventions for generative AI systems. The trace structure is consistent across different underlying frameworks (like LangChain, OpenAI, or Google), though the specific content within the spans may vary depending on the framework being used.
  3. Key features of any-agent

    main

    any-agent provides a unified interface for managing agents across various ecosystems. Key capabilities include:

    • Framework Agnosticism: Switch between supported frameworks (Agno, Google ADK, LangChain, LlamaIndex, OpenAI, smolagents, and TinyAgent) by changing a single parameter.
    • Unified Tracing: Standardized OpenTelemetry traces across all frameworks for consistent observability.
    • Built-in Evaluation: Tools for LLM-as-a-judge and agent-as-a-judge evaluation to assess performance.
    • Interoperability: Ability to serve agents via A2A or MCP protocols and compose them as tools for other agents.
  4. Choose an agent evaluation method

    main

    The any-agent evaluation module provides three distinct approaches for evaluating agent traces, depending on your requirements for speed, cost, and complexity:

    1. Custom Code Evaluation: Best for deterministic checks, performance metrics (like token counts), and specific criteria. It is fast, reliable, and cost-effective but requires manual coding.
    2. LlmJudge: Best for simple qualitative assessments and text-based evaluations. It is easy to set up and flexible but can be inconsistent and costs more than code.
    3. AgentJudge: Best for complex multi-step evaluations and tool usage analysis. It is the most flexible as it can use tools to inspect the trace or external information, but it is the slowest and most expensive.
  5. The Callback Contract in any-agent

    main

    When implementing custom callbacks by subclassing Callback, you must adhere to the following contract:

    1. Receive Context: Callbacks receive a context object of type Context.
    2. Shared State: You can store and persist data across different callback executions using context.shared (a dictionary-like object).
    3. Return Context: Every callback method must return the context object to allow the execution chain to continue.
    4. Modify Spans: You can access and modify the current trace span via context.current_span to inspect or scrub attributes (e.g., using span.set_attribute).
    from any_agent.callbacks import Callback, Context
    
    class MyCustomCallback(Callback):
        def before_tool_execution(self, context: Context, *args, **kwargs) -> Context:
            # 1. Use context.shared for state
            context.shared["my_key"] = 123
            
            # 2. MUST return context
            return context
  6. Inspect AgentTrace properties and tool usage

    main

    An AgentTrace object contains the execution history of an agent. You can access metadata like duration, cost, and tokens, as well as iterate through spans to inspect specific steps.

    To verify if a specific tool was used, iterate through the spans and check if span.is_tool_execution() is true, then inspect the span.attributes using the GenAI.TOOL_NAME key.

    Key properties available on AgentTrace:

    • duration: Total execution time.
    • cost: Total monetary cost of the run.
    • tokens: Total token count (trace.tokens.total_tokens).
    • final_output: The agent's final response.
    • spans: A list of execution steps/spans.
    from any_agent.tracing.agent_trace import AgentTrace
    from any_agent.tracing.attributes import GenAI
    
    # Example: Checking if a tool was used
    def check_tool_usage(trace: AgentTrace, required_tool: str) -> bool:
        return any(
            span.attributes[GenAI.TOOL_NAME] == required_tool
            for span in trace.spans
            if span.is_tool_execution()
        )
  7. Choose between any-agent and standalone TinyAgent

    main

    TinyAgent is available in two ways:

    1. Via any-agent: any-agent re-exposes TinyAgent to provide a consistent multi-framework abstraction. Use this if you want to switch between different agent frameworks easily.
    2. Standalone: TinyAgent ships as its own package, mozilla-ai-tinyagent. Install this directly if you do not need the multi-framework abstraction provided by any-agent and want to minimize dependencies.
  8. Quickstart: Create an agent with AnyAgent

    main

    To define an agent system, use the AnyAgent.create method with an AgentConfig object. This allows you to specify the framework (e.g., tinyagent), the model, instructions, and a list of tools.

    Before running, ensure you have set the necessary environment variables for your model provider (e.g., MISTRAL_API_KEY or OPENAI_API_KEY).

    Supported frameworks include: Agno, Google ADK, LangChain, LlamaIndex, OpenAI Agents SDK, smolagents, and TinyAgent.

    from any_agent import AgentConfig, AnyAgent
    from any_agent.tools import search_web, visit_webpage
    
    # Ensure environment variables like MISTRAL_API_KEY are set
    
    agent = AnyAgent.create(
        "tinyagent",  # Framework name
        AgentConfig(
            model_id="mistral:mistral-small-latest",
            instructions="Use the tools to find an answer",
            tools=[search_web, visit_webpage]
        )
    )
    
    agent_trace = agent.run("Which Agent Framework is the best??")
    print(agent_trace)
  9. Install dependencies for MCP agents

    main

    To use Model Context Protocol (MCP) servers with any-agent, you need to install any-agent and the specific MCP server packages. If running in a Jupyter notebook, you must also use nest_asyncio to enable nested event loops for asyncio support.

    %pip install 'any-agent' 'mcp-server-time' --quiet
    
    import nest_asyncio
    
    nest_asyncio.apply()
  10. Install any-agent

    main

    Prerequisites

    • Python 3.11 or newer

    Installation Options

    Bare bones installation Installs the core library. Note that only TinyAgent will be available in this mode.

    pip install any-agent

    Framework-specific installation To use specific frameworks, install the library with the corresponding extras. For example, to include support for Agno and OpenAI:

    pip install any-agent[agno,openai]

    For a full list of available framework extras, refer to the pyproject.toml file in the repository.

  11. Serve an agent using the A2A protocol

    main

    You can expose an agent to other applications using the A2A protocol by calling await agent.serve_async(). This method returns a handle that provides access to the server's port and a shutdown() method.

    To configure the server, pass an A2AServingConfig object to serve_async. Setting port=0 allows the system to assign an available ephemeral port.

    Example setup with an MCP tool:

    from any_agent import AgentConfig, AnyAgent
    from any_agent.config import MCPStdio
    from any_agent.serving import A2AServingConfig
    
    # Define a tool using MCP (Model Context Protocol)
    time_tool = MCPStdio(
        command="python",
        args=["-u", "-m", "mcp_server_time", "--local-timezone", "America/New_York"],
        tools=["get_current_time"],
        client_session_timeout_seconds=30,
    )
    
    # Create the agent
    agent = await AnyAgent.create_async(
        "my-agent",
        AgentConfig(
            model_id="mistral:mistral-small-latest",
            description="An agent that tells time",
            tools=[time_tool],
        ),
    )
    
    # Start the A2A server
    time_handle = await agent.serve_async(A2AServingConfig(port=0))
    server_port = time_handle.port
    time_handle = await time.serve_async(A2AServingConfig(port=0))
    server_port = time_handle.port
  12. Install dependencies for any-agent

    main

    To use any-agent, install the package along with ddgs (for DuckDuckGo search tools). If you are working in a Jupyter notebook, you must also install and apply nest_asyncio to support nested event loops required by the asyncio module used by any-agent.

    %pip install 'any-agent' --quiet
    %pip install ddgs --quiet
    
    import nest_asyncio
    nest_asyncio.apply()