Contributing
How to set up the monorepo, run tests, create changesets, add a new wrapper, and open a pull request.
This page is generated from
CONTRIBUTING.mdand stays in sync with the repository.
Thanks for your interest in contributing! This is a monorepo containing multiple packages — this guide covers how to work across all of them.
Prerequisites
- Node.js >= 20.0.0
- npm (comes with Node.js)
Repository Structure
a2a-wrapper/
├── packages/
│ └── core/ # @a2a-wrapper/core — shared infrastructure
├── a2a-claude/ # a2a-claude — Claude wrapper
├── a2a-copilot/ # a2a-copilot — GitHub Copilot SDK wrapper
├── a2a-opencode/ # a2a-opencode — OpenCode wrapper
├── a2a-codex/ # a2a-codex — OpenAI Codex SDK wrapper
├── a2a-antigravity/ # a2a-antigravity — Google Antigravity SDK wrapper
├── turbo.json # Turborepo task pipeline
├── .changeset/ # Changesets versioning config
└── package.json # Root workspace configpackages/core/— shared library (@a2a-wrapper/core): logging, config loading, event publishing, server factory, session management, CLI scaffolda2a-claude/— A2A wrapper for Claudea2a-copilot/— A2A wrapper for GitHub Copilot SDKa2a-opencode/— A2A wrapper for OpenCodea2a-codex/— A2A wrapper for OpenAI Codex SDKa2a-antigravity/— A2A wrapper for Google Antigravity SDK using a private Python subprocess
All packages are managed via npm workspaces and built with Turborepo.
Getting Started
# Clone the repository
git clone https://github.com/shashikanth-gs/a2a-wrapper.git
cd a2a-wrapper
# Install dependencies for all packages (from the repo root)
npm install
# Build all packages so @a2a-wrapper/core is compiled to dist/
# (dist/ is git-ignored and is NOT produced by `npm install`)
npx turbo run buildA single npm install at the root resolves dependencies for every package and hoists shared ones. Note that npm install does not compile anything — @a2a-wrapper/core is consumed from its built dist/ output, so run npx turbo run build before running any package or example.
Development Commands
All commands run from the repository root using Turborepo:
# Build all packages (core builds first, then wrappers in parallel)
npx turbo run build
# Run tests across all packages
npx turbo run test
# Type-check all packages
npx turbo run typecheck
# Clean build artifacts
npx turbo run cleanTurborepo caches build outputs — unchanged packages are skipped on subsequent runs.
Working on a Specific Package
You can scope Turborepo to a single package with --filter:
# Build only core
npx turbo run build --filter=@a2a-wrapper/core
# Test only a2a-copilot
npx turbo run test --filter=a2a-copilot
# Build a2a-opencode and its dependencies
npx turbo run build --filter=a2a-opencode...
# Test only a2a-antigravity
npx turbo run test --filter=a2a-antigravityOr work directly inside a package directory:
cd packages/core
npm test
cd a2a-copilot
npm test
cd a2a-antigravity
npm testCreating Changesets
This project uses Changesets for versioning and changelogs. Every PR that changes package behavior should include a changeset.
# Create a new changeset (interactive prompt)
npx changesetThe CLI will ask you:
- Which packages were affected
- The semver bump type (patch / minor / major)
- A summary of the change
This creates a markdown file in .changeset/ — commit it with your PR.
When to create a changeset
- Bug fixes →
patch - New features (backward-compatible) →
minor - Breaking changes →
major - Documentation-only or CI-only changes → no changeset needed
Release Process
Once a PR is merged to main, three things happen automatically:
- CI re-validates
main(build, typecheck, test). - Canary publish — once CI succeeds, every affected package is published to npm under the
canarydist-tag with a snapshot version like1.8.0-canary-20260812070958. Install one withnpm install <package>@canary. This never touchesmain— the snapshot version bump happens only in the CI runner and is discarded, so pending changesets are left intact. - Version Packages PR — the Changesets bot opens/updates a PR on
mainthat batches all pending changesets into real version bumps and CHANGELOG entries.
When a maintainer merges the Version Packages PR, the release workflow checks whether a release is ready (no pending changesets and at least one package version not yet published) and, if so, waits for manual approval via the release GitHub Environment before running npx changeset publish under the latest dist-tag and creating GitHub releases.
So npm install <package> always gets the latest approved stable release, while npm install <package>@canary gets the most recent merge to main.
Both the canary and stable-release publish steps live in the single .github/workflows/publish.yml file, as separate jobs. This is required, not stylistic: npm Trusted Publishing allows exactly one trusted publisher per package, bound to one workflow filename, so every path that can call npm publish for these packages has to originate from that one file. version.yml (the Version Packages PR bot) is a separate file because it never publishes to npm.
Adding a New Wrapper
Adding a new A2A wrapper (e.g. a2a-claude) requires no changes to the root config or core package:
-
Create a directory at the repo root following the
a2a-<name>naming convention:a2a-claude/ ├── package.json ├── tsconfig.json ├── src/ │ ├── index.ts │ ├── cli.ts │ ├── server/ │ │ └── index.ts # Thin delegate to core's createA2AServer │ └── claude/ │ ├── executor.ts # Implements A2AExecutor │ ├── session-manager.ts │ └── config/ │ ├── types.ts # Extends BaseAgentConfig │ └── defaults.ts └── agents/ └── example/ └── config.json -
In
package.json, set:nametoa2a-<name>@a2a-wrapper/coreas a dependency ("*")publishConfig.accessto"public"- A
build,test, andtypecheckscript
-
Implement the
A2AExecutorinterface from@a2a-wrapper/coreand wire it up withcreateCli().src/server/index.tsmust be a thin delegate to core'screateA2AServer()— do not hand-roll Express routing, agent card building, or event publishing. All A2A protocol wiring (agent card, JSON-RPC/REST transports, v1.0/v0.3 version negotiation) lives in@a2a-wrapper/coreon purpose, so every wrapper gets protocol updates for free. Follow the pattern in any existinga2a-*/src/server/index.ts— callcreateA2AServer(config, executorFactory, options)and useregisterRoutesfor wrapper-specific endpoints only. -
Run
npm installat the repo root to link the new package. -
Verify everything works:
npx turbo run build test typecheck -
Create a changeset for the initial release:
npx changeset
The a2a-* workspace glob in the root package.json automatically picks up the new directory — no config edits needed.
Pull Request Process
- Fork the repo and create a feature branch from
main. - Make your changes and add tests where appropriate.
- Run the full build and test suite:
npx turbo run build typecheck test - Create a changeset if your change affects published packages:
npx changeset - Open a pull request against
main. CI will build and test across Node.js 20 and 22. - Address review feedback and ensure CI passes.
Code of Conduct
This project follows the Contributor Covenant Code of Conduct. Please read it before participating.
Docs MCP server
Connect Claude Code, Cursor, VS Code or any MCP client to the a2a-wrapper documentation. A read-only MCP server over Streamable HTTP with search_docs, get_page and list_pages tools.
Roadmap
What is planned for a2a-wrapper. OpenTelemetry observability and other upcoming work, and how to propose changes.