CLI tool
a2aproject/a2a-js avatar
a2aproject/a2a-js

a2a-js: the official JavaScript SDK for the Agent2Agent protocol

Official JavaScript SDK for the Agent2Agent (A2A) Protocol

647 stars179 forksTypeScriptApache-2.0

At a glance

What is it?
@a2a-js/sdk is the official TypeScript and JavaScript SDK for the A2A protocol, giving you one DefaultRequestHandler behind three wire transports, an opt-in compatibility layer for v0.3 peers, and persistent task stores with a migrations CLI. It suits teams building agent servers or clients in Node, and it commits you to the A2A message and task model rather than letting you invent one.
Who is it for?
a2a-js is the right choice if you are building an A2A server or client in Node and want the protocol surface, the task lifecycle and the transport bindings handled by the official implementation rather than by hand. It is the wrong choice for a browser-only agent, since the gRPC transport is Node-only and the package requires Node 20 or newer, and it is the wrong choice if your peers are still firmly on v0.3 and you would rather wait for the compatibility layer to stabilise.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Installing the SDK and choosing a transport

The base install is a single command:

bash
npm install @a2a-js/sdk

Everything else is a peer dependency you add only if you use that part. The Express integration, which imports from @a2a-js/sdk/server/express, needs Express:

bash
npm install express

The gRPC transport, imported from @a2a-js/sdk/server/grpc or @a2a-js/sdk/client/grpc, needs the gRPC runtime and the protobuf tooling:

bash
npm install @grpc/grpc-js @bufbuild/protobuf

Persistent stores, imported from @a2a-js/sdk/server/database, need Kysely and a driver:

bash
npm install kysely <driver>  # pg / mysql2 / better-sqlite3 / kysely-d1 (Cloudflare D1)

The SDK covers both sides of the A2A protocol. A server is an agent exposing its capabilities over the protocol; a client is an application discovering and driving those agents. The project describes itself as a JavaScript library that helps run agentic applications as A2A servers following the Agent2Agent protocol, and as the official TypeScript and JavaScript SDK for it.

The architectural decision worth understanding is that all three transports are backed by a single DefaultRequestHandler. JSON-RPC, HTTP+JSON/REST and gRPC are alternative wire encodings over the same core handler, not three separate implementations. The compatibility table confirms the symmetry: every transport has both a client and a server side. The practical consequence is that switching a deployment from REST to gRPC is a transport configuration change rather than a rewrite, and that the task semantics you write once apply everywhere.

One limitation is stated plainly in the README: the gRPC transport is Node.js only. The package manifest sets the engines field to node >=20 and the module type to module, and the build outputs both an ESM entry and a require entry through the exports map, so CommonJS consumers are supported, but the runtime floor and the gRPC restriction together rule out edge and browser deployments for the parts of the SDK that talk gRPC.

Subpath exports and where each piece lives

The package is organised entirely through subpath exports, and the typesVersions map in the manifest shows the full surface: errors, errors/grpc, server, server/express, server/grpc, server/database, client, client/grpc, and six compat/v0_3 entries covering the base, server, express, grpc, client and client/grpc variants.

That layout is informative because it tells you the dependency direction. The core errors module is separate from the gRPC error helpers, so code that only handles protocol errors does not pull in the gRPC stack. The database entry point is separate from the server entry point, which means persistence is opt in at the import level rather than something a server picks up by default. The compat entries mirror the main layout exactly, which is what a compatibility layer that has to sit underneath every transport tends to look like.

The server/database and server/express subpaths also explain the install instructions. Using the Express integration means importing from @a2a-js/sdk/server/express, and since Express is a peer dependency rather than a bundled one, you install it yourself. The same pattern applies to the gRPC transport with @grpc/grpc-js and @bufbuild/protobuf, and to persistent stores with Kysely plus a driver. Peer dependencies here are the right design for a library that has to work inside someone else's server, but it does mean the install step is a decision tree rather than one command.

The v0.3 compatibility layer is opt in, and that is the point

Protocol migrations are where SDKs usually hurt. The A2A protocol reached a v1.0 stable release, and this SDK implements the v1.0.0 specification, but deployments in the field may still include peers on v0.3. The SDK's answer is an opt-in compatibility layer, described as v0.3 backward compatibility so that v1.0 deployments can interoperate with v0.3 peers during a staged migration.

Opt in is the important word. Nothing about the compatibility behaviour is active unless you ask for it, so a v1.0 deployment is not silently speaking an older dialect to a client that expects v1.0 semantics. The compat-v1-server sample shows the shape of it, with legacyCompat set to enabled true on every transport: JSON-RPC, REST, gRPC, the agent card and push notifications all carry the compatibility switch.

The compat-v1-client sample pairs that with a hand-rolled mock v0.3 server run in process, which is the right way to test the negotiation without a second machine. For anyone upgrading from 0.3.x, the repository ships a migration guide at docs/migration-guide.md and a separate v0.3 compatibility guide at docs/compatibility-v0_3.md, and the README is explicit that the specification, not the SDK, is the source of truth for message formats, task lifecycle states, transport bindings, push notifications, extensions and authentication.

Task lifecycle, cancellation and push notifications in the samples

The sample directory is the best documentation of the protocol's task model, and the entries are deliberately small. The sample-agent is a minimal streaming agent showing the task lifecycle from submitted to working to artifact to completed over JSON-RPC. The cancellable-agent implements cancelTask so a user can abort an in-flight task, which is the difference between an agent that can only finish and one that can be stopped.

The push-notification-agent is a long-running agent that POSTs task updates to a client-provided webhook, and the sample list describes it as covering server, webhook and client together. That is the mechanism for an agent whose work outlives the request that started it, and it is the part of A2A that most affects your infrastructure, since it means your service makes outbound HTTP calls to a URL the caller supplied.

The authentication sample uses server-side Bearer and JWT authentication with Passport, and includes a UserBuilder that propagates the authenticated user into the agent context, which is how you get identity from the transport layer into your business logic without threading it manually. The extensions sample implements a protocol extension as an AgentExecutor decorator that adds metadata to outgoing events, and the verify-signing sample does client-side verification of signed agent cards using JWS and JWKS, which is the discovery-time counterpart to request-time authentication.

Persistent stores and the a2a-db migration CLI

Long-running agents need their tasks and push notification configurations to survive a restart, and the SDK offers persistent stores in PostgreSQL, MySQL, SQLite or Cloudflare D1, with an a2a-db CLI for migrations.

The store layer is built on Kysely, and the driver is yours to choose, with the install line naming pg, mysql2, better-sqlite3 and kysely-d1 for Cloudflare D1. Kysely being the query layer means the SQL is generated rather than hand written, and the SQLite and D1 options mean the same code can run in a test process and on D1 without a separate persistence implementation. The trade is that Cloudflare D1 sits behind an HTTP API rather than a socket, so latency characteristics differ from a local SQLite file even though the code path is identical.

The CLI is the part that deserves attention in a review. A schema migration tool is a piece of operational tooling, and whoever runs it decides when the schema changes. The README names the command and the supported databases but does not describe the migration workflow, rollback behaviour or whether migrations are safe to run against a live traffic-serving deployment. Before you adopt the persistent store, run the migrations against a real database in a staging environment and read the tool's own output, rather than discovering the failure mode during a deploy.

Interceptors, the interactive CLI and the project layout

On the client side, the interceptor sample covers header injection and request timing, plus a per-call AbortSignal.timeout call, which is how you attach an API key to every outbound request and cap how long a call may hang. The interactive cli.ts sample is a multi-transport client for JSON-RPC, REST and gRPC with --auth and --svc-param header injection flags, which is also a useful manual test tool against a running server.

The repository layout shows a project with real engineering behind it. There are three separate Vitest configurations, vitest.config.ts, vitest.edge.config.ts and vitest.integration.config.ts, so unit, edge and integration tests are separated rather than lumped together. The itk/ directory and tck/ directory are worth noting: a TCK, a test compatibility kit, is a way of checking that an implementation follows the specification rather than only its own tests, and acts/ appears to be a GitHub Actions workflow directory for the same reason. A conformance suite is a stronger signal than a test coverage number, because it is written against the spec.

The build is tsup, the release process is release-please with a manifest and config, and the top level also carries AGENTS.md, SECURITY.md, CODE_OF_CONDUCT.md and CONTRIBUTING.md. The licence is Apache-2.0, which is the permissive choice with an explicit patent grant, and no legal interpretation is needed beyond noting that an Apache-2.0 SDK can be embedded in a commercial product without copyleft obligations.

Editorial conclusion

a2a-js is the right choice if you are building an A2A server or client in Node and want the protocol surface, the task lifecycle and the transport bindings handled by the official implementation rather than by hand. It is the wrong choice for a browser-only agent, since the gRPC transport is Node-only and the package requires Node 20 or newer, and it is the wrong choice if your peers are still firmly on v0.3 and you would rather wait for the compatibility layer to stabilise. Before adopting it, read the migration guide if you are coming from 0.3.x, confirm your persistence needs by running the a2a-db CLI migrations against a real database rather than assuming the SQLite default, and check that the spec version your peers speak matches the v1.0.0 surface this SDK implements.

Frequently asked questions

How do I install the A2A JavaScript SDK?

Run npm install @a2a-js/sdk. Peer dependencies are extra: npm install express for the Express integration, npm install @grpc/grpc-js @bufbuild/protobuf for the gRPC transport, and npm install kysely with a driver for persistent stores.

Which transports does @a2a-js/sdk support?

Three: JSON-RPC, HTTP+JSON/REST and gRPC, each with both a client and a server implementation, all backed by a single DefaultRequestHandler. The gRPC transport is Node.js only.

Can an a2a-js server talk to a peer still on A2A v0.3?

Yes, through an opt-in v0.3 compatibility layer. The compat-v1-server sample enables legacyCompat on every transport, and a separate v0.3 compatibility guide is published under docs/.

What databases can I use for persistent tasks in @a2a-js/sdk?

PostgreSQL, MySQL, SQLite and Cloudflare D1 are supported through Kysely, with an a2a-db CLI for migrations. The driver is a peer dependency you install yourself, for example pg, mysql2, better-sqlite3 or kysely-d1.

What licence is the A2A JavaScript SDK under?

Apache-2.0. The repository is not archived and the last push was on 2026-10-19, with v1.3.0 released on 2026-09-29, v1.2.1 on 2026-09-24 and v1.2.0 on 2026-09-18.

Official sources

  1. a2aproject/a2a-js on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/a2aproject-a2a-js.svg)](https://hysenlabs.com/projects/a2aproject-a2a-js)

Was this useful?