Install
pipx is recommended so the CLI lands in its own venv on $PATH. pip works inside a project venv too.
# recommended
pipx install a2a-pack
# or, inside a project venv
pip install a2a-packVerify: a2a --help
A2A compliance, deployable
a2a-pack turns Python or TypeScript/JS agent code into a hosted A2A service. You write typed tools around the framework you already use. The SDK and runtime handle AgentCard, task lifecycle, message parts, file exchange, structured data, artifacts, streaming, bearer auth, protocol errors.
Read Google's Agent2Agent announcement ↗, then build with the small surface below.
import a2a_pack as a2a
from a2a_pack import A2AAgent, NoAuth, RunContext
class Research(A2AAgent):
name = "research-agent"
description = "Summarizes URLs."
@a2a.tool(description="Summarize the page at url.")
async def summarize(self, ctx: RunContext[NoAuth], url: str) -> dict:
return {"url": url, "summary": await summarize_url(url)}
# a2a deploy
# -> AgentCard, A2A tasks/messages, REST, JSON-RPC, SSE, MCP, auth, artifactsQuick start
Writes a token to ~/.a2a/credentials.json — the same file a2amcp reads.
a2a signup # first time
a2a login # already have an accounta2a init research-agent
cd research-agentYou get agent.py, a2a.yaml, requirements.txt.
Subclass A2AAgent. Each @a2a.tool-decorated async def becomes both an HTTP endpoint and an MCP tool.
import a2a_pack as a2a
from a2a_pack import A2AAgent, NoAuth, RunContext
class Research(A2AAgent):
name = "research-agent"
description = "Summarizes URLs."
@a2a.tool(description="Summarize the page at `url` in N bullets.")
async def summarize(
self, ctx: RunContext[NoAuth], url: str, bullets: int = 5
) -> dict:
text = await fetch_page(url)
return {"url": url, "bullets": summarize(text, bullets)}a2a validate # type-checks the agent + prints skill count
a2a card # prints the public AgentCard JSONa2a deployTarballs source. Uploads to the control plane. Builds the service. Publishes the runtime surface. Returns live URL.
Every deployed agent serves three protocols. Pick one per caller:
# 1. HTTP API
curl https://research-agent.a2acloud.io/.well-known/agent-card
# 2. MCP (in your editor, via the gateway)
a2a mcp-url research-agentfrom a2a_pack import HttpA2AClient
client = HttpA2AClient()
call = await client.call(
"https://research-agent.a2acloud.io",
"summarize",
args={"url": "https://...", "bullets": 3},
)
result = call.resultOptional: ship a frontend app
If the workflow needs upload controls, review screens, approvals, reports, or artifacts — scaffold a packed React app. Frontend reads the generated contract from /app/config.json and invokes inferred tools through the same hosted runtime.
a2a init chart-agent --frontend react
cd chart-agent
a2a dev
# in another terminal
cd frontend
npm install
npm run devfrontend:
path: frontend
build: npm run build
dist: dist
mount: /app
auth: inheritDeploy runs the frontend build, copies the static bundle into the agent image, serves at /app. Read the packed frontend docs ↗.
What deploy creates
- HTTPS servicePer-agent endpoint with health checks, docs, managed HTTPS.
- AgentCardGET /.well-known/agent-card describes identity, skills, schemas, auth.
- Packed appOptional /app frontend with generated config, schemas, session-aware calls.
- A2A + MCPTask protocol and POST /mcp on every agent. No extra adapter.
- Sandboxed runtimeCode-running tools execute behind the workspace boundary.
- Scoped filesGrant negotiation gives each run explicit read/write authority.
- Progress eventsSSE streams status, tool work, questions, artifacts.
- Receipts and evalsRuns preserve args, file ops, results, scores, review notes.
- Private or publicKeep internal, or publish to registry discovery later.
Production controls
Private first
Deploy internally. Trial real files. Publish only when run history is strong.
Approval-aware
Agents request expanded scope rather than receive broad creds up front.
Replay-ready
Receipts, artifacts, eval metadata make version comparison practical.
CLI reference
| command | what it does |
|---|---|
| a2a signup | Create an account on the control plane. |
| a2a login | Authenticate; cache the JWT locally. |
| a2a whoami | Show the logged-in account. |
| a2a init <name> | Scaffold a new agent project. |
| a2a init <name> --frontend react | Scaffold an agent plus packed React/Vite frontend. |
| a2a frontend build | Run the declared frontend build and verify dist/index.html. |
| a2a validate | Load the agent class and validate its declaration. |
| a2a card | Print the AgentCard JSON for the current project. |
| a2a run -e module:Class | Run the agent locally on http://127.0.0.1:8000. |
| a2a deploy | Tarball, upload, build, deploy. Returns the public URL. |
| a2a agents | List agents visible to your account. |
| a2a mcp-url <name> | Print the MCP config snippet for a deployed agent. |
| a2a build | Build a container image locally (advanced). |
Project layout
research-agent/ agent.py # subclass A2AAgent, decorate methods with @a2a.tool a2a.yaml # name, version, entrypoint module:Class requirements.txt # whatever your agent imports frontend/ # optional React/Vite app when --frontend react
a2a.yaml is the only config you maintain. The control plane derives the rest from the agent class declaration.
Secrets & env
Declare what the agent needs on the class. Deploy flow surfaces missing values up-front instead of failing at first request.
class Research(A2AAgent):
name = "research-agent"
required_secrets = ("ANTHROPIC_API_KEY",)
required_env = ("USER_AGENT",)Troubleshooting
- a2a: command not found? Re-run with pipx ensurepath, then open a new shell.
- Deploy hangs at "still building"? Check a2a agents — first build pulls layers, can take a few minutes.
- 401 on /invoke? If auth_model = APIKeyAuth, set A2A_API_KEY and send Authorization: Bearer <key>.