Catalog PyPI
PACKAGE EXPLORERView in registry

a2a-smol-adapter

PyPI

Bridge between smolagents and the A2A (Agent2Agent) protocol

a2aagent2agentinteroperabilitymulti-agentsmolagents
Versions collected1
Direct dependencies9From release 0.1.0
Last observed20 Oct, 16:29 UTC

README

Version 0.1.0 documentation

A2A-Smol-Adapter

Python 3.10+ License: MIT Tests Ruff

Bridge between smolagents (HuggingFace) and the A2A protocol (Google).

Expose any smolagents CodeAgent as an A2A-compliant server, or delegate tasks from a CodeAgent to remote A2A agents — in a few lines of Python.

Why?

The Agent2Agent (A2A) protocol is an open standard for agent interoperability. smolagents is HuggingFace's lightweight agent framework. This library bridges both, enabling:

  • Your smolagents agents to be discoverable and callable by any A2A-compatible client
  • Your agents to delegate work to any remote A2A agent (LangChain, CrewAI, Google ADK, etc.)
  • Multi-agent systems where agents from different frameworks collaborate seamlessly

Features

FeatureDescription
A2A ServerWrap a CodeAgent in a FastAPI server that speaks JSON-RPC 2.0
A2A Client Toolsmolagents.Tool to delegate work to any remote A2A agent
Agent CardAuto-generated discovery endpoint at /.well-known/agent-card.json
API Key AuthOptional Bearer token authentication on server and client
SSE StreamingIntermediate progress events via message/stream
Retry with BackoffExponential backoff on transient network errors (client)
Configurable TimeoutServer-side agent execution timeout with proper failure events
Health EndpointGET /health for Kubernetes liveness/readiness probes

Installation

pip install a2a-smol-adapter

Or from source:

git clone https://github.com/billyboy06/a2a-smol-adapter.git
cd a2a-smol-adapter
pip install -e ".[dev]"

Quick Start

Expose an agent as A2A server

import os
from smolagents import CodeAgent, InferenceClientModel
from a2a_smol_adapter import SmolA2AServer

agent = CodeAgent(tools=[], model=InferenceClientModel())

server = SmolA2AServer(
    agent,
    name="my-agent",
    host="0.0.0.0",             # listen on all interfaces (default: 127.0.0.1)
    port=5001,
    api_key=os.environ.get("A2A_API_KEY"),  # optional auth via env var
    agent_timeout=60.0,         # optional timeout (default: 120s)
)
server.run()
# Agent card → http://localhost:5001/.well-known/agent-card.json
# Health     → http://localhost:5001/health

Delegate to a remote A2A agent

import os
from smolagents import CodeAgent, InferenceClientModel
from a2a_smol_adapter import SmolA2ADelegateTool

delegate = SmolA2ADelegateTool(
    remote_url="http://remote-agent:5001/",
    api_key=os.environ.get("A2A_API_KEY"),  # optional, matches server auth
    max_retries=2,              # retry on network errors (default: 2)
)

agent = CodeAgent(tools=[delegate], model=InferenceClientModel())
result = agent.run("Ask the remote agent to compute pi to 50 digits")

Architecture

┌──────────────────┐          ┌──────────────────────────────────────┐
│  Any A2A Client  │          │  SmolA2AServer                      │
│  (LangChain,     │  JSON-   │  ┌──────────┐  ┌────────────────┐  │
│   CrewAI,        │  RPC 2.0 │  │ FastAPI   │  │ SmolAgent      │  │
│   Google ADK,    │ ────────►│  │ + Auth    │─►│ Executor       │  │
│   curl...)       │          │  │ + Health  │  │ (async bridge) │  │
└──────────────────┘          │  └──────────┘  └───────┬────────┘  │
                              │                        │           │
                              │                ┌───────▼────────┐  │
                              │                │ smolagents     │  │
                              │                │ CodeAgent.run()│  │
                              │                └────────────────┘  │
                              └──────────────────────────────────────┘

┌──────────────────────────────────────┐          ┌──────────────────┐
│  Your smolagents CodeAgent           │          │  Any A2A Server  │
│  ┌────────────────────────────────┐  │  JSON-   │  (this lib,      │
│  │ SmolA2ADelegateTool            │  │  RPC 2.0 │   Google ADK,    │
│  │ (auto-retry, auth, timeout)   │──│─────────►│   LangChain...)  │
│  └────────────────────────────────┘  │          └──────────────────┘
└──────────────────────────────────────┘

API Reference

SmolA2AServer

SmolA2AServer(
    agent: CodeAgent,
    *,
    name: str = "smol-agent",
    description: str = "...",
    version: str = "0.1.0",
    host: str = "127.0.0.1",
    port: int = 5000,
    skills: list[dict] | None = None,
    api_key: str | None = None,        # Bearer token auth
    agent_timeout: float = 120.0,      # seconds before timeout
)
MethodDescription
run()Start the uvicorn server
build_app()Return the FastAPI app (for custom deployments, ASGI)
agent_cardThe A2A AgentCard with name, skills, capabilities

SmolA2ADelegateTool

SmolA2ADelegateTool(
    remote_url: str = "",
    timeout: float = 120.0,
    api_key: str | None = None,        # Bearer token for remote server
    max_retries: int = 2,              # retries on ConnectError/Timeout
    http_client: httpx.Client | None = None,  # injectable for testing
)

Usable as a standard smolagents.Tool — add it to your agent's tool list and call via delegate_to_a2a(url, task).

Testing

pip install -e ".[dev]"

# Run all 69 tests
pytest -v

# Lint
ruff check src/ tests/

Test coverage includes:

  • Unit tests for server executor, client tool, auth middleware, healthcheck
  • Integration tests with full cycle: discovery → send task → receive artifact
  • Auth scenarios: valid key, invalid key, missing key, exempt paths
  • Retry behavior: exponential backoff, exhausted retries, no retry on 4xx/5xx
  • Timeout: agent execution timeout with proper failure events
  • Streaming: intermediate working events from agent steps

Project Structure

src/a2a_smol_adapter/
├── __init__.py         # Public API: SmolA2AServer, SmolA2ADelegateTool
├── server.py           # A2A server, executor, auth middleware, healthcheck
└── client_tool.py      # A2A client tool with retry, auth, DI

tests/
├── test_server.py      # 38 tests — executor, auth, streaming, health
├── test_client_tool.py # 23 tests — retry, auth header, DI, extraction
└── integration/
    └── test_end_to_end.py  # 8 tests — full cycle with ASGI transport

examples/
├── basic_server.py     # Minimal server setup
└── basic_client.py     # Minimal client delegation

Security Considerations

  • API key comparison uses hmac.compare_digest (timing-safe) to prevent side-channel attacks
  • Default host is 127.0.0.1 (localhost only) — use host="0.0.0.0" explicitly for network-facing deployments
  • Prompt size is capped at 100KB to prevent abuse
  • No rate limiting built-in — use a reverse proxy (nginx, Traefik) for rate limiting in production
  • Security headers (HSTS, CSP, etc.) are the responsibility of your reverse proxy
  • Prompt injection: CodeAgent generates and executes Python code from user prompts. Use smolagents' sandboxing features (LocalPythonExecutor restrictions) when exposing to untrusted users
  • Consumer responsibility: error messages from remote agents are returned as-is — escape them before rendering in HTML contexts
  • API keys should be loaded from environment variables, never hardcoded (see examples)

Built With

License

MIT

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.08 Mar 20269

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
billyboy06/a2a-smol-adapter

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 16:29 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:b4bfc85475bdc0fa46a002ab9813a11570aa7413e64321cf1f733669dd2cb791