Agent Stack Documentation

repository·main·Indexed 22 days ago

https://github.com/i-am-bee/agentstack

An open infrastructure for turning AI agents into production-ready services. It provides a Server SDK to wrap agents from frameworks like LangChain, CrewAI, and BeeAI into HTTP services using the Agent2Agent (A2A) protocol, and a Client SDK for TypeScript/JavaScript applications to interact with agents, handle streaming messages, and manage service and UI extensions.

Tokens
173.3K
Snippets
492
Records
661
Agent score
77%

What's inside Agent Stack

  1. Overview of Agent Stack capabilities

    main

    Agent Stack is an open infrastructure designed to turn AI agents into running services. It is built on the Agent2Agent (A2A) Protocol and provides several core components:

    • Agent Runtime: A self-hostable server for production agent execution.
    • LLM & AI Services: Support for 15+ providers (Anthropic, OpenAI, watsonx.ai, Ollama) and vector search for RAG.
    • Deployment & Management: CLI tools for managing agent lifecycles.
    • Storage & Documents: S3-compatible file storage and document extraction via Docling.
    • Interfaces: A Web UI for testing and a Client SDK for custom applications.
    • Integrations: Support for the Model Context Protocol (MCP) for external tools (Slack, Google Drive, etc.).
    • Security: Secrets management and OAuth support.
    • Interoperability: Automatically exposes agents as A2A-compatible, allowing them to work with frameworks like LangGraph or CrewAI.
  2. Integrate existing agents with the Agent Stack Server SDK (Python)

    main

    The Agent Stack Server SDK is a Python library designed to wrap existing AI agents (built with LangGraph, CrewAI, or custom logic) and connect them to the Agent Stack platform. It is built on the Agent2Agent Protocol (A2A) and uses A2A extensions to provide access to platform services like LLM providers, file storage, vector databases, and rich UI components without requiring a rewrite of your core logic.

    Key features include:

    • Server wrapper: Simplified server creation and agent registration.
    • Convenience wrappers: Simplified message types like AgentMessage.
    • Context management: Built-in conversation history and state management.
    • Async generator pattern: Support for task-based execution with pause/resume capabilities.
    • Dependency Injection Extensions: Access to LLM services, RAG embeddings, file storage, and MCP integration.
    • UI Extensions: Support for interactive components like forms, citations, and trajectory visualization.
    import os
    from a2a.types import Message
    from agentstack_sdk.server import Server
    
    server = Server()
    
    @server.agent()
    async def my_agent(input: Message, context: RunContext):
        yield AgentMessage(text="Hello!")
    
    if __name__ == "__main__":
        server.run(host=os.getenv("HOST", "127.0.0.1"), port=int(os.getenv("PORT", 8000)))
  3. Core components of Agent Stack

    main

    Agent Stack provides a bundled runtime with the following capabilities:

    ComponentWhat's Included
    Agent RuntimeSelf-hostable server to run agents in production
    LLM & AI ServicesLLM service (15+ providers like Anthropic, OpenAI, watsonx.ai, Ollama) and Embeddings/Vector search
    Agent Deployment & ManagementCLI for deploying, updating, and managing agents
    Storage & DocumentsS3-compatible file storage and Docling-based text extraction
    Interfaces & ToolingWeb UI for testing and Client SDK for custom UIs
    IntegrationsMCP protocol support (APIs, Slack, Google Drive, etc.) with OAuth
    SecuritySecrets management and OAuth support
    DeploymentHelm chart for Kubernetes
    InteroperabilityFramework agnostic (LangGraph, CrewAI, etc.); agents are exposed as A2A-compatible services
  4. What is Agent Stack?

    main

    Agent Stack (formerly BeeAI Platform) is open infrastructure designed for deploying and sharing AI agents to production. It provides a framework-agnostic deployment layer that works with any agent logic (e.g., LangGraph, CrewAI, BeeAI Framework, or custom code) via the agentstack-sdk and A2A protocol extensions.

    Core Components:

    • Server: A self-hostable runtime for agents.
    • Web UI: An interface for users to interact with deployed agents.
    • CLI Tool: For deploying and managing agents.
    • Infrastructure Services:
      • Runtime-configurable LLMs (15+ providers like Anthropic, OpenAI, watsonx.ai, Ollama).
      • Embeddings & vector search (for RAG).
      • File storage (S3-compatible).
      • Document text extraction (via Docsling).
      • External integrations (via MCP protocol with built-in OAuth).
      • Secrets management (encrypted credential storage).
    • SDK: Allows agents to request infrastructure services at runtime.
    • Helm Chart: For custom infrastructure configuration (S3, databases, auth, etc.).
  5. How the LLM Proxy Service works

    main

    The LLM Proxy Service provides model and provider-agnostic LLM inference. It uses the 'Service Extension' pattern (an A2A Extension) to implement inversion of control: your agent defines its LLM requirements via type hints, and the Agent Stack platform is responsible for injecting the necessary dependencies.

    When you request a specific model, the platform:

    1. Checks availability in the configured environment.
    2. Allocates the best matching model.
    3. Provides the exact model identifier and endpoint details.

    Because the service provides OpenAI-compatible credentials, you can use the resolved configuration with any standard OpenAI-compatible client library (e.g., LangChain, LlamaIndex, or the official OpenAI Python client).

    # The extension is added as an Annotated parameter in your agent function
    async def my_agent(
        input: Message, 
        llm: Annotated[LLMServiceExtensionServer, ...]
    ):
        pass
  6. Understand Agent Stack authentication tokens

    main

    Agent Stack uses two distinct types of authentication tokens to control access to platform resources:

    1. User Tokens: Issued via OIDC/OAuth for human users. These provide full access based on the user's role (USER, DEVELOPER, or ADMIN).
    2. Context Tokens: Generated programmatically for agents. These are designed for limited, scoped access during a specific conversation (context).
  7. Manage sensitive credentials with Agent Secrets

    main

    Use the Agent Secrets feature via the A2A service dependency extension to securely request and manage credentials (like API keys) from users.

    Workflow:

    1. Declaration: Agents declare required secrets that must be provided before execution.
    2. User Prompt: The UI prompts the user to provide or refuse the secret.
    3. Just-in-time requests: Agents can delay requesting secrets until they are absolutely necessary during the conversation flow.
  8. Manage conversation history with RunContext

    main

    Agent Stack provides a context memory system to maintain conversation continuity. While agent functions are stateless, you can use RunContext to access and manage conversation history.

    Key Operations

    OperationPurpose
    await context.store(input)Explicitly stores the current user message in the conversation history.
    await context.store(response)Explicitly stores the agent's response in the conversation history.
    context: RunContextThe type used in agent function signatures to provide access to history.
    context_store=PlatformContextStore()Configuration used when starting the server to ensure history persists across agent restarts.

    Implementation Steps

    1. Access history: Include context: RunContext in your agent function signature.
    2. Store incoming messages: Call await context.store(input) to save the user's message.
    3. Retrieve history: Use context.load_history() to load previous messages.
    4. Store agent responses: Call await context.store(response) to save your agent's output for future turns.
    @server.agent()
    async def my_agent(input: Message, context: RunContext):
        # Store user input
        await context.store(input)
        
        # Load history
        history = [msg async for msg in context.load_history() if isinstance(msg, Message)]
        
        # Generate response
        response = AgentMessage(text="Hello!")
        yield response
        
        # Store agent response
        await context.store(response)
  9. Request secrets dynamically during runtime

    main

    If the required secrets are not pre-configured, your agent can pause and request them from the user during execution using await secrets.request_secrets(). This is useful for conditional requirements or when a secret is only needed after a specific agent action.

    You must pass a SecretsServiceExtensionParams object containing a dictionary of SecretDemand objects, where the keys are the secret identifiers.

    try:
        runtime_provided_secrets = await secrets.request_secrets(
            params=SecretsServiceExtensionParams(
                secret_demands={
                    "SLACK_API_KEY": SecretDemand(description="I really need Slack Key", name="Slack")
                }
            )
        )
    except ValueError:
        runtime_provided_secrets = None
    
    if runtime_provided_secrets and runtime_provided_secrets.secret_fulfillments:
        val = runtime_provided_secrets.secret_fulfillments['SLACK_API_KEY'].secret.get_secret_value()
  10. Use the Asynchronous Generator Pattern for task execution

    main

    Agent functions in the SDK are implemented as asynchronous generators. This pattern maps directly to the A2A task model:

    • One function execution = One A2A task
    • Yielding data = Sending messages to the client
    • Pausing execution = Waiting for user input

    This allows agents to stream responses incrementally, yield multiple messages during a single task, and handle long-running operations or user interruptions gracefully.