├── .git-blame-ignore-revs ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ └── feature-request.yml ├── PULL_REQUEST_TEMPLATE.md ├── actions │ └── spelling │ │ ├── advice.md │ │ ├── allow.txt │ │ ├── excludes.txt │ │ └── line_forbidden.patterns ├── conventional-commit-lint.yaml ├── linters │ ├── .eslintrc.js │ ├── .jscpd.json │ ├── .markdownlint.json │ └── .stylelintrc.json ├── release-please.yml ├── release-trigger.yml └── workflows │ ├── dispatch-a2a-update.yml │ ├── docs.yml │ ├── generate-a2a-json.yml │ ├── issue-metrics.yml │ ├── links.yaml │ ├── linter.yaml │ ├── spelling.yaml │ └── stale.yaml ├── .gitignore ├── .prettierrc ├── .ruff.toml ├── .vscode └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── docs ├── README.md ├── assets │ ├── a2a-actors.png │ ├── a2a-banner.png │ ├── a2a-logo-black.svg │ ├── a2a-logo-white.svg │ ├── a2a-main.png │ ├── a2a-mcp-readme.png │ └── a2a-mcp.png ├── community.md ├── index.md ├── llms.txt ├── partners.md ├── robots.txt ├── sdk │ └── python │ │ └── index.md ├── specification.md ├── stylesheets │ └── custom.css ├── topics │ ├── a2a-and-mcp.md │ ├── agent-discovery.md │ ├── enterprise-ready.md │ ├── key-concepts.md │ ├── streaming-and-async.md │ └── what-is-a2a.md └── tutorials │ └── python │ ├── 1-introduction.md │ ├── 2-setup.md │ ├── 3-agent-skills-and-card.md │ ├── 4-agent-executor.md │ ├── 5-start-server.md │ ├── 6-interact-with-server.md │ ├── 7-streaming-and-multiturn.md │ └── 8-next-steps.md ├── lychee.toml ├── mkdocs.yml ├── noxfile.py ├── requirements-docs.txt ├── specification ├── grpc │ └── a2a.proto └── json │ ├── README.md │ └── a2a.json └── types ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── src └── types.ts └── tsconfig.json /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Template taken from https://github.com/v8/v8/blob/master/.git-blame-ignore-revs. 2 | # 3 | # This file contains a list of git hashes of revisions to be ignored by git blame. These 4 | # revisions are considered "unimportant" in that they are unlikely to be what you are 5 | # interested in when blaming. Most of these will probably be commits related to linting 6 | # and code formatting. 7 | # 8 | # Instructions: 9 | # - Only large (generally automated) reformatting or renaming CLs should be 10 | # added to this list. Do not put things here just because you feel they are 11 | # trivial or unimportant. If in doubt, do not put it on this list. 12 | # - Precede each revision with a comment containing the PR title and number. 13 | # For bulk work over many commits, place all commits in a block with a single 14 | # comment at the top describing the work done in those commits. 15 | # - Only put full 40-character hashes on this list (not short hashes or any 16 | # other revision reference). 17 | # - Append to the bottom of the file (revisions should be in chronological order 18 | # from oldest to newest). 19 | # - Because you must use a hash, you need to append to this list in a follow-up 20 | # PR to the actual reformatting PR that you are trying to ignore. 21 | 0f8d9750bcb17f6b8b9f48793b46f7b8510cae24 22 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Code owners file. 2 | # This file controls who is tagged for review for any given pull request. 3 | # 4 | # For syntax help see: 5 | # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax 6 | 7 | * @google-a2a/googlers 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: 🐞 Bug Report 2 | description: File a bug report 3 | title: "[Bug]: " 4 | type: "Bug" 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for stopping by to let us know something could be better! 10 | Private Feedback? Please use this [Google form](https://goo.gle/a2a-feedback) 11 | - type: textarea 12 | id: what-happened 13 | attributes: 14 | label: What happened? 15 | description: Also tell us what you expected to happen and how to reproduce the issue. 16 | placeholder: Tell us what you see! 17 | value: "A bug happened!" 18 | validations: 19 | required: true 20 | - type: textarea 21 | id: logs 22 | attributes: 23 | label: Relevant log output 24 | description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. 25 | render: shell 26 | - type: checkboxes 27 | id: terms 28 | attributes: 29 | label: Code of Conduct 30 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/google-a2a/A2A?tab=coc-ov-file#readme) 31 | options: 32 | - label: I agree to follow this project's Code of Conduct 33 | required: true 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: 💡 Feature Request 2 | description: Suggest an idea for this repository 3 | title: "[Feat]: " 4 | type: "Feature" 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for stopping by to let us know something could be better! 10 | Private Feedback? Please use this [Google form](https://goo.gle/a2a-feedback) 11 | - type: textarea 12 | id: problem 13 | attributes: 14 | label: Is your feature request related to a problem? Please describe. 15 | description: A clear and concise description of what the problem is. 16 | placeholder: Ex. I'm always frustrated when [...] 17 | - type: textarea 18 | id: describe 19 | attributes: 20 | label: Describe the solution you'd like 21 | description: A clear and concise description of what you want to happen. 22 | validations: 23 | required: true 24 | - type: textarea 25 | id: alternatives 26 | attributes: 27 | label: Describe alternatives you've considered 28 | description: A clear and concise description of any alternative solutions or features you've considered. 29 | - type: textarea 30 | id: context 31 | attributes: 32 | label: Additional context 33 | description: Add any other context or screenshots about the feature request here. 34 | - type: checkboxes 35 | id: terms 36 | attributes: 37 | label: Code of Conduct 38 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/google-a2a/A2A?tab=coc-ov-file#readme) 39 | options: 40 | - label: I agree to follow this project's Code of Conduct 41 | required: true 42 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | Thank you for opening a Pull Request! 4 | Before submitting your PR, there are a few things you can do to make sure it goes smoothly: 5 | 6 | - [ ] Follow the [`CONTRIBUTING` Guide](https://github.com/google-a2a/A2A/blob/main/CONTRIBUTING.md). 7 | - [ ] Make your Pull Request title in the specification. 8 | - [ ] Ensure the tests and linter pass (Run `nox -s format` from the repository root to format) 9 | - [ ] Appropriate docs were updated (if necessary) 10 | 11 | Fixes # 🦕 12 | -------------------------------------------------------------------------------- /.github/actions/spelling/advice.md: -------------------------------------------------------------------------------- 1 | 2 |
If the flagged items are :exploding_head: false positives 3 | 4 | If items relate to a ... 5 | 6 | - binary file (or some other file you wouldn't want to check at all). 7 | 8 | Please add a file path to the `excludes.txt` file matching the containing file. 9 | 10 | File paths are Perl 5 Regular Expressions - you can [test](https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files. 11 | 12 | `^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude `README.md` (on whichever branch you're using). 13 | 14 | - well-formed pattern. 15 | 16 | If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it, 17 | try adding it to the `patterns.txt` file. 18 | 19 | Patterns are Perl 5 Regular Expressions - you can [test](https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines. 20 | 21 | Note that patterns can't match multiline strings. 22 | 23 |
24 | 25 | 26 | 27 | :steam_locomotive: If you're seeing this message and your PR is from a branch that doesn't have check-spelling, 28 | please merge to your PR's base branch to get the version configured for your repository. 29 | -------------------------------------------------------------------------------- /.github/actions/spelling/allow.txt: -------------------------------------------------------------------------------- 1 | AAAANSUh 2 | AAAAUA 3 | AAAGHMHc 4 | ACMRTUXB 5 | ACard 6 | AClient 7 | ACo 8 | ADK 9 | AError 10 | AIP 11 | ARequest 12 | ASED 13 | ASGI 14 | AServer 15 | AService 16 | AStarlette 17 | Autogen 18 | CAs 19 | CLIs 20 | Camry 21 | Cjava 22 | DDo 23 | DGT 24 | Dotnet 25 | EBFF 26 | EUR 27 | EUg 28 | FBT 29 | GAPI 30 | GAPIC 31 | GBP 32 | GVsb 33 | Gapic 34 | Genkit 35 | Ghw 36 | IFdvcmxk 37 | INR 38 | JHv 39 | JPY 40 | JWKS 41 | JWTs 42 | KGgo 43 | KRW 44 | LHR 45 | LLM 46 | LLMs 47 | MWpm 48 | OIDC 49 | OOa 50 | Ollama 51 | PLE 52 | PLW 53 | PTH 54 | RPCs 55 | RUF 56 | SLAs 57 | SLF 58 | TMDB 59 | URLTo 60 | Upserting 61 | Urke 62 | VBORw 63 | Vsb 64 | WVw 65 | Witteveen 66 | Xca 67 | YTT 68 | YWFh 69 | Zipkin 70 | aab 71 | aacacac 72 | aboutasha 73 | achat 74 | aconnect 75 | adk 76 | agentcard 77 | agentic 78 | agentskill 79 | ainvoke 80 | aparse 81 | arxiv 82 | askmarvin 83 | asyncclick 84 | autogen 85 | autouse 86 | backstory 87 | backticks 88 | bbb 89 | bzr 90 | cae 91 | ccc 92 | cdn 93 | ceee 94 | cfe 95 | cls 96 | coc 97 | codegen 98 | codeowner 99 | crewai 100 | datamodel 101 | datapart 102 | dbc 103 | dcda 104 | dcfa 105 | dde 106 | direnv 107 | documentai 108 | dotnet 109 | efaab 110 | efbd 111 | embeddings 112 | envoyproxy 113 | evt 114 | excinfo 115 | faa 116 | fafd 117 | ffbb 118 | firewalls 119 | flightbook 120 | fsv 121 | fyi 122 | gapic 123 | gcp 124 | genai 125 | genkit 126 | genproto 127 | georoute 128 | gettickets 129 | gle 130 | googleai 131 | googleapi 132 | googleblog 133 | gpt 134 | gstatic 135 | gweb 136 | iat 137 | ietf 138 | inbox 139 | inmemory 140 | iss 141 | jherr 142 | jti 143 | jwks 144 | kty 145 | langgraph 146 | linenums 147 | linkedin 148 | llm 149 | llms 150 | lng 151 | marvin 152 | mcp 153 | mesop 154 | mindsdb 155 | mozilla 156 | msword 157 | multiagent 158 | multipage 159 | nlp 160 | notif 161 | noxfile 162 | npush 163 | objc 164 | octicons 165 | ollama 166 | oneof 167 | prefecthq 168 | protolint 169 | pyguide 170 | pymdownx 171 | pypackages 172 | pytype 173 | pyupgrade 174 | qwq 175 | rcm 176 | reportgen 177 | reposted 178 | rvelicheti 179 | sllm 180 | squidfunk 181 | srcs 182 | sse 183 | stateclass 184 | styleguide 185 | svn 186 | systemctl 187 | tagwords 188 | taskssend 189 | taskstate 190 | taskstatus 191 | textpart 192 | threadsafe 193 | tok 194 | tracestate 195 | ugc 196 | utm 197 | versioned 198 | vnd 199 | voa 200 | webpage 201 | whatwg 202 | wikipedia 203 | wsgi 204 | wwwwwwww 205 | xxxxx 206 | xxxxxxxx 207 | youtube 208 | yyyyyyyy 209 | zzzzzzzz 210 | -------------------------------------------------------------------------------- /.github/actions/spelling/excludes.txt: -------------------------------------------------------------------------------- 1 | # See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-excludes 2 | (?:^|/)(?i)COPYRIGHT 3 | (?:^|/)(?i)LICEN[CS]E 4 | (?:^|/)(?i)CODE_OF_CONDUCT.md\E$ 5 | (?:^|/)(?i).gitignore\E$ 6 | (?:^|/)3rdparty/ 7 | (?:^|/)go\.sum$ 8 | (?:^|/)package(?:-lock|)\.json$ 9 | (?:^|/)Pipfile$ 10 | (?:^|/)pyproject.toml 11 | (?:^|/)requirements(?:-dev|-doc|-test|)\.txt$ 12 | (?:^|/)vendor/ 13 | /CODEOWNERS$ 14 | \.a$ 15 | \.ai$ 16 | \.all-contributorsrc$ 17 | \.avi$ 18 | \.bmp$ 19 | \.bz2$ 20 | \.cer$ 21 | \.class$ 22 | \.coveragerc$ 23 | \.crl$ 24 | \.crt$ 25 | \.csr$ 26 | \.dll$ 27 | \.docx?$ 28 | \.drawio$ 29 | \.DS_Store$ 30 | \.eot$ 31 | \.eps$ 32 | \.exe$ 33 | \.gif$ 34 | \.git-blame-ignore-revs$ 35 | \.gitattributes$ 36 | \.gitkeep$ 37 | \.graffle$ 38 | \.gz$ 39 | \.icns$ 40 | \.ico$ 41 | \.jar$ 42 | \.jks$ 43 | \.jpe?g$ 44 | \.key$ 45 | \.lib$ 46 | \.lock$ 47 | \.map$ 48 | \.min\.. 49 | \.mo$ 50 | \.mod$ 51 | \.mp[34]$ 52 | \.o$ 53 | \.ocf$ 54 | \.otf$ 55 | \.p12$ 56 | \.parquet$ 57 | \.pdf$ 58 | \.pem$ 59 | \.pfx$ 60 | \.png$ 61 | \.psd$ 62 | \.pyc$ 63 | \.pylintrc$ 64 | \.qm$ 65 | \.s$ 66 | \.sig$ 67 | \.so$ 68 | \.svgz?$ 69 | \.sys$ 70 | \.tar$ 71 | \.tgz$ 72 | \.tiff?$ 73 | \.ttf$ 74 | \.wav$ 75 | \.webm$ 76 | \.webp$ 77 | \.woff2?$ 78 | \.xcf$ 79 | \.xlsx?$ 80 | \.xpm$ 81 | \.xz$ 82 | \.zip$ 83 | ^\.github/actions/spelling/ 84 | ^\Q.github/workflows/spelling.yaml\E$ 85 | ^\Q.github/workflows/linter.yaml\E$ 86 | ^\Qdemo/ui/service/server/test_image.py\E$ 87 | ^\Qlychee.toml\E$ 88 | \.vscode/ 89 | ^\Qdocs/partners.md\E$ 90 | ^\Qspecification/json/a2a.json\E$ 91 | CHANGELOG.md 92 | \.gitignore 93 | ^\Qdocs/robots.txt\E$ 94 | -------------------------------------------------------------------------------- /.github/actions/spelling/line_forbidden.patterns: -------------------------------------------------------------------------------- 1 | # Should be `HH:MM:SS` 2 | \bHH:SS:MM\b 3 | 4 | # Should probably be `YYYYMMDD` 5 | \b[Yy]{4}[Dd]{2}[Mm]{2}(?!.*[Yy]{4}[Dd]{2}[Mm]{2}).*$ 6 | 7 | # Should be `anymore` 8 | \bany more[,.] 9 | 10 | # Should be `cannot` (or `can't`) 11 | # See https://www.grammarly.com/blog/cannot-or-can-not/ 12 | # > Don't use `can not` when you mean `cannot`. The only time you're likely to see `can not` written as separate words is when the word `can` happens to precede some other phrase that happens to start with `not`. 13 | # > `Can't` is a contraction of `cannot`, and it's best suited for informal writing. 14 | # > In formal writing and where contractions are frowned upon, use `cannot`. 15 | # > It is possible to write `can not`, but you generally find it only as part of some other construction, such as `not only . . . but also.` 16 | # - if you encounter such a case, add a pattern for that case to patterns.txt. 17 | \b[Cc]an not\b 18 | 19 | # Should be `GitHub` 20 | (?> $GITHUB_ENV 38 | - uses: actions/cache@v4 39 | with: 40 | key: mkdocs-material-${{ env.cache_id }} 41 | path: .cache 42 | restore-keys: | 43 | mkdocs-material- 44 | 45 | - name: Install documentation dependencies 46 | run: pip install -r requirements-docs.txt && pip install a2a-sdk 47 | 48 | - name: Build Documentation (PR Check) 49 | if: github.event_name == 'pull_request' 50 | run: mkdocs build 51 | 52 | - name: Build and Deploy Documentation (Push to main) 53 | if: github.event_name == 'push' && github.ref == 'refs/heads/main' 54 | run: mkdocs gh-deploy --force 55 | -------------------------------------------------------------------------------- /.github/workflows/generate-a2a-json.yml: -------------------------------------------------------------------------------- 1 | name: Auto-generate A2A JSON Schema 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | paths: 8 | - "types/src/types.ts" 9 | types: 10 | - opened 11 | - synchronize 12 | - reopened 13 | 14 | jobs: 15 | generate_json: 16 | name: Generate JSON Schema 17 | runs-on: ubuntu-latest 18 | permissions: 19 | contents: write 20 | 21 | steps: 22 | - name: Checkout Code 23 | uses: actions/checkout@v4 24 | with: 25 | fetch-depth: 0 26 | ref: ${{ github.event.pull_request.head.ref }} 27 | repository: ${{ github.event.pull_request.head.repo.full_name }} 28 | 29 | - name: Setup Node.js 30 | uses: actions/setup-node@v4 31 | with: 32 | node-version: "20" 33 | 34 | - name: Install dependencies and generate a2a.json 35 | working-directory: types 36 | run: | 37 | npm install 38 | npm run generate 39 | id: generate_schema 40 | 41 | - name: Configure Git for Bot 42 | if: github.event.pull_request.head.repo.full_name == github.repository 43 | run: | 44 | git config user.name "a2a-bot" 45 | git config user.email "a2a-bot@google.com" 46 | 47 | - name: Check for Changes 48 | id: git_status 49 | run: | 50 | git add specification/json/a2a.json 51 | if ! git diff --cached --quiet --exit-code; then 52 | echo "changes_detected=true" >> "$GITHUB_OUTPUT" 53 | echo "a2a.json is not up-to-date with types.ts" 54 | else 55 | echo "a2a.json is up-to-date." 56 | fi 57 | 58 | - name: Commit and Push Changes (if on base repository) 59 | if: steps.git_status.outputs.changes_detected == 'true' && github.event.pull_request.head.repo.full_name == github.repository 60 | run: | 61 | git commit -m "chore: Auto-generate a2a.json from types.ts changes" 62 | git push 63 | 64 | - name: Fail on Fork PR if Changes Required 65 | if: steps.git_status.outputs.changes_detected == 'true' && github.event.pull_request.head.repo.full_name != github.repository 66 | run: | 67 | echo "::error::a2a.json is out of date." 68 | echo "Please run 'npm install' then 'npm run generate' in the 'types' directory of your branch and commit the updated 'specification/json/a2a.json' file." 69 | exit 1 # Exit with a non-zero code to fail the workflow 70 | -------------------------------------------------------------------------------- /.github/workflows/issue-metrics.yml: -------------------------------------------------------------------------------- 1 | name: Monthly issue metrics 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | - cron: "3 2 1 * *" 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | build: 12 | name: issue metrics 13 | runs-on: ubuntu-latest 14 | permissions: 15 | issues: write 16 | pull-requests: read 17 | steps: 18 | - name: Get dates for last month 19 | shell: bash 20 | run: | 21 | # Calculate the first day of the previous month 22 | first_day=$(date -d "last month" +%Y-%m-01) 23 | 24 | # Calculate the last day of the previous month 25 | last_day=$(date -d "$first_day +1 month -1 day" +%Y-%m-%d) 26 | 27 | # Set an environment variable with the date range 28 | echo "$first_day..$last_day" 29 | echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" 30 | 31 | - name: Run issue-metrics tool 32 | uses: github/issue-metrics@v3 33 | env: 34 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | SEARCH_QUERY: 'repo:google-a2a/A2A is:issue created:${{ env.last_month }} -reason:"not planned"' 36 | 37 | - name: Create issue 38 | uses: peter-evans/create-issue-from-file@v5 39 | with: 40 | title: Monthly issue metrics report 41 | token: ${{ secrets.GITHUB_TOKEN }} 42 | content-filepath: ./issue_metrics.md 43 | -------------------------------------------------------------------------------- /.github/workflows/links.yaml: -------------------------------------------------------------------------------- 1 | name: Links 2 | 3 | on: 4 | repository_dispatch: 5 | workflow_dispatch: 6 | schedule: 7 | - cron: "00 18 * * *" 8 | 9 | jobs: 10 | linkChecker: 11 | runs-on: ubuntu-latest 12 | if: | 13 | github.repository == 'google-a2a/A2A' 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - name: Link Checker 19 | id: lychee 20 | uses: lycheeverse/lychee-action@v2 21 | 22 | - name: Create Issue From File 23 | if: env.lychee_exit_code != 0 24 | uses: peter-evans/create-issue-from-file@v5 25 | with: 26 | title: Link Checker Report 27 | content-filepath: ./lychee/out.md 28 | labels: report, automated issue 29 | -------------------------------------------------------------------------------- /.github/workflows/linter.yaml: -------------------------------------------------------------------------------- 1 | ################################# 2 | ################################# 3 | ## Super Linter GitHub Actions ## 4 | ################################# 5 | ################################# 6 | name: Lint Code Base 7 | 8 | # 9 | # Documentation: 10 | # https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions 11 | # 12 | 13 | ############################# 14 | # Start the job on all push # 15 | ############################# 16 | on: 17 | pull_request: 18 | branches: [main] 19 | 20 | ############### 21 | # Set the Job # 22 | ############### 23 | jobs: 24 | build: 25 | # Name the Job 26 | name: Lint Code Base 27 | # Set the agent to run on 28 | runs-on: ubuntu-latest 29 | # if on repo to avoid failing runs on forks 30 | if: | 31 | github.repository == 'google-a2a/A2A' 32 | 33 | ################## 34 | # Load all steps # 35 | ################## 36 | steps: 37 | ########################## 38 | # Checkout the code base # 39 | ########################## 40 | - name: Checkout Code 41 | uses: actions/checkout@v4 42 | with: 43 | # Full git history is needed to get a proper list of changed files within `super-linter` 44 | fetch-depth: 0 45 | 46 | ################################ 47 | # Run Linter against code base # 48 | ################################ 49 | - name: Lint Code Base 50 | uses: super-linter/super-linter/slim@v7 51 | env: 52 | DEFAULT_BRANCH: main 53 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 54 | LOG_LEVEL: WARN 55 | SHELLCHECK_OPTS: -e SC1091 -e 2086 56 | VALIDATE_ALL_CODEBASE: false 57 | FILTER_REGEX_EXCLUDE: "^(\\.github/|\\.vscode/).*|CODE_OF_CONDUCT.md|CHANGELOG.md" 58 | VALIDATE_PYTHON_BLACK: false 59 | VALIDATE_PYTHON_FLAKE8: false 60 | VALIDATE_PYTHON_ISORT: false 61 | VALIDATE_PYTHON_MYPY: false 62 | VALIDATE_PYTHON_PYLINT: false 63 | VALIDATE_PYTHON_PYINK: false 64 | VALIDATE_CHECKOV: false 65 | VALIDATE_JAVASCRIPT_STANDARD: false 66 | VALIDATE_TYPESCRIPT_STANDARD: false 67 | VALIDATE_NATURAL_LANGUAGE: false 68 | MARKDOWN_CONFIG_FILE: ".markdownlint.json" 69 | VALIDATE_MARKDOWN_PRETTIER: false 70 | TYPESCRIPT_ES_CONFIG_FILE: ".eslintrc.js" 71 | VALIDATE_JAVASCRIPT_PRETTIER: false 72 | VALIDATE_JSON_PRETTIER: false 73 | VALIDATE_YAML_PRETTIER: false 74 | VALIDATE_GIT_COMMITLINT: false 75 | -------------------------------------------------------------------------------- /.github/workflows/spelling.yaml: -------------------------------------------------------------------------------- 1 | name: Check Spelling 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "**" 7 | types: 8 | - "opened" 9 | - "reopened" 10 | - "synchronize" 11 | issue_comment: 12 | types: 13 | - "created" 14 | 15 | jobs: 16 | spelling: 17 | name: Check Spelling 18 | permissions: 19 | contents: read 20 | actions: read 21 | security-events: write 22 | outputs: 23 | followup: ${{ steps.spelling.outputs.followup }} 24 | runs-on: ubuntu-latest 25 | # if on repo to avoid failing runs on forks 26 | if: | 27 | github.repository == 'google-a2a/A2A' 28 | && (contains(github.event_name, 'pull_request') || github.event_name == 'push') 29 | concurrency: 30 | group: spelling-${{ github.event.pull_request.number || github.ref }} 31 | # note: If you use only_check_changed_files, you do not want cancel-in-progress 32 | cancel-in-progress: false 33 | steps: 34 | - name: check-spelling 35 | id: spelling 36 | uses: check-spelling/check-spelling@main 37 | with: 38 | suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }} 39 | checkout: true 40 | check_file_names: 1 41 | spell_check_this: check-spelling/spell-check-this@main 42 | post_comment: 0 43 | use_magic_file: 1 44 | report-timing: 1 45 | warnings: bad-regex,binary-file,deprecated-feature,ignored-expect-variant,large-file,limited-references,no-newline-at-eof,noisy-file,non-alpha-in-dictionary,token-is-substring,unexpected-line-ending,whitespace-in-dictionary,minified-file,unsupported-configuration,no-files-to-check,unclosed-block-ignore-begin,unclosed-block-ignore-end 46 | experimental_apply_changes_via_bot: 1 47 | dictionary_source_prefixes: '{"cspell": "https://raw.githubusercontent.com/streetsidesoftware/cspell-dicts/main/dictionaries/"}' 48 | extra_dictionaries: | 49 | cspell:aws/dict/aws.txt 50 | cspell:bash/samples/bash-words.txt 51 | cspell:companies/dict/companies.txt 52 | cspell:css/dict/css.txt 53 | cspell:data-science/dict/data-science-models.txt 54 | cspell:data-science/dict/data-science.txt 55 | cspell:data-science/dict/data-science-tools.txt 56 | cspell:en_shared/dict/acronyms.txt 57 | cspell:en_shared/dict/shared-additional-words.txt 58 | cspell:en_GB/en_GB.trie 59 | cspell:en_US/en_US.trie 60 | cspell:filetypes/src/filetypes.txt 61 | cspell:fonts/dict/fonts.txt 62 | cspell:fullstack/dict/fullstack.txt 63 | cspell:golang/dict/go.txt 64 | cspell:google/dict/google.txt 65 | cspell:html/dict/html.txt 66 | cspell:java/src/java.txt 67 | cspell:k8s/dict/k8s.txt 68 | cspell:mnemonics/dict/mnemonics.txt 69 | cspell:monkeyc/src/monkeyc_keywords.txt 70 | cspell:node/dict/node.txt 71 | cspell:npm/dict/npm.txt 72 | cspell:people-names/dict/people-names.txt 73 | cspell:python/dict/python.txt 74 | cspell:python/dict/python-common.txt 75 | cspell:shell/dict/shell-all-words.txt 76 | cspell:software-terms/dict/softwareTerms.txt 77 | cspell:software-terms/dict/webServices.txt 78 | cspell:sql/src/common-terms.txt 79 | cspell:sql/src/sql.txt 80 | cspell:sql/src/tsql.txt 81 | cspell:terraform/dict/terraform.txt 82 | cspell:typescript/dict/typescript.txt 83 | check_extra_dictionaries: "" 84 | only_check_changed_files: true 85 | longest_word: "10" 86 | -------------------------------------------------------------------------------- /.github/workflows/stale.yaml: -------------------------------------------------------------------------------- 1 | # This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. 2 | # 3 | # You can adjust the behavior by modifying this file. 4 | # For more information, see: 5 | # https://github.com/actions/stale 6 | name: Mark stale issues and pull requests 7 | 8 | on: 9 | schedule: 10 | # Scheduled to run at 10.30PM UTC everyday (1530PDT/1430PST) 11 | - cron: "30 22 * * *" 12 | workflow_dispatch: 13 | 14 | jobs: 15 | stale: 16 | runs-on: ubuntu-latest 17 | permissions: 18 | issues: write 19 | pull-requests: write 20 | actions: write 21 | 22 | steps: 23 | - uses: actions/stale@v9 24 | with: 25 | repo-token: ${{ secrets.GITHUB_TOKEN }} 26 | days-before-issue-stale: 14 27 | days-before-issue-close: 13 28 | stale-issue-label: "status:stale" 29 | close-issue-reason: not_planned 30 | any-of-labels: "status:awaiting response,status:more data needed" 31 | stale-issue-message: > 32 | Marking this issue as stale since it has been open for 14 days with no activity. 33 | This issue will be closed if no further activity occurs. 34 | close-issue-message: > 35 | This issue was closed because it has been inactive for 27 days. 36 | Please post a new issue if you need further assistance. Thanks! 37 | days-before-pr-stale: 14 38 | days-before-pr-close: 13 39 | stale-pr-label: "status:stale" 40 | stale-pr-message: > 41 | Marking this pull request as stale since it has been open for 14 days with no activity. 42 | This PR will be closed if no further activity occurs. 43 | close-pr-message: > 44 | This pull request was closed because it has been inactive for 27 days. 45 | Please open a new pull request if you need further assistance. Thanks! 46 | # Label that can be assigned to issues to exclude them from being marked as stale 47 | exempt-issue-labels: "override-stale" 48 | # Label that can be assigned to PRs to exclude them from being marked as stale 49 | exempt-pr-labels: "override-stale" 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *.pyc 5 | *$py.class 6 | **/dist 7 | /tmp 8 | /out-tsc 9 | /bazel-out 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | .eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | wheels/ 28 | pip-wheel-metadata/ 29 | share/python-wheels/ 30 | *.egg-info/ 31 | .installed.cfg 32 | *.egg 33 | MANIFEST 34 | 35 | # PyInstaller 36 | # Usually these files are written by a python script from a template 37 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 38 | *.manifest 39 | *.spec 40 | 41 | # Installer logs 42 | pip-log.txt 43 | pip-delete-this-directory.txt 44 | 45 | # Unit test / coverage reports 46 | htmlcov/ 47 | .tox/ 48 | .nox/ 49 | .coverage 50 | .coverage.* 51 | .cache 52 | nosetests.xml 53 | coverage.xml 54 | *.cover 55 | *.py,cover 56 | .hypothesis/ 57 | .pytest_cache/ 58 | 59 | # Translations 60 | *.mo 61 | *.pot 62 | 63 | # Django stuff: 64 | *.log 65 | local_settings.py 66 | db.sqlite3 67 | db.sqlite3-journal 68 | 69 | # Flask stuff: 70 | instance/ 71 | .webassets-cache 72 | 73 | # Scrapy stuff: 74 | .scrapy 75 | 76 | # Sphinx documentation 77 | docs/_build/ 78 | 79 | # PyBuilder 80 | target/ 81 | 82 | # Jupyter Notebook 83 | .ipynb_checkpoints 84 | 85 | # IPython 86 | profile_default/ 87 | ipython_config.py 88 | 89 | # pyenv 90 | .python-version 91 | 92 | # pipenv 93 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 94 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 95 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 96 | # install all needed dependencies. 97 | Pipfile.lock 98 | Pipfile 99 | 100 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 101 | __pypackages__/ 102 | 103 | # Celery stuff 104 | celerybeat-schedule 105 | celerybeat.pid 106 | 107 | # SageMath parsed files 108 | *.sage.py 109 | 110 | # Environments 111 | .env 112 | .venv 113 | .venv* 114 | env/ 115 | venv/ 116 | ENV/ 117 | env.bak/ 118 | venv.bak/ 119 | 120 | # Spyder project settings 121 | .spyderproject 122 | .spyproject 123 | 124 | # Rope project settings 125 | .ropeproject 126 | 127 | # mkdocs documentation 128 | /site 129 | 130 | # mypy 131 | .mypy_cache/ 132 | .dmypy.json 133 | dmypy.json 134 | .ruff_cache/ 135 | 136 | # Pyre type checker 137 | .pyre/ 138 | 139 | # macOS 140 | .DS_Store 141 | 142 | # PyCharm 143 | .idea 144 | 145 | # User-specific files 146 | language/examples/prompt-design/train.csv 147 | README-TOC*.md 148 | 149 | # Terraform 150 | terraform.tfstate** 151 | .terraform* 152 | .Terraform* 153 | 154 | tmp* 155 | 156 | # Node 157 | **/node_modules 158 | npm-debug.log 159 | yarn-error.log 160 | 161 | # IDEs and editors 162 | .idea/ 163 | .project 164 | .classpath 165 | .c9/ 166 | *.launch 167 | .settings/ 168 | *.sublime-workspace 169 | 170 | # Miscellaneous 171 | **/.angular/* 172 | /.angular/cache 173 | .sass-cache/ 174 | /connect.lock 175 | /coverage 176 | /libpeerconnection.log 177 | testem.log 178 | /typings 179 | 180 | # System files 181 | .DS_Store 182 | Thumbs.db 183 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "trailingComma": "es5", 4 | "bracketSameLine": true 5 | } 6 | -------------------------------------------------------------------------------- /.ruff.toml: -------------------------------------------------------------------------------- 1 | ################################################################################# 2 | # 3 | # Ruff linter and code formatter for A2A 4 | # 5 | # This file follows the standards in Google Python Style Guide 6 | # https://google.github.io/styleguide/pyguide.html 7 | # 8 | # The settings below are for the IDE configuration, and are optional. 9 | #{ 10 | # "editor.formatOnSave": true, 11 | # "[python]": { 12 | # "editor.defaultFormatter": "charliermarsh.ruff", 13 | # "editor.formatOnSave": true, 14 | # "editor.codeActionsOnSave": { 15 | # "source.organizeImports": "true" 16 | # }, 17 | # }, 18 | # "ruff.importStrategy": "fromEnvironment", 19 | #} 20 | 21 | line-length = 80 # Google Style Guide §3.2: 80 columns 22 | indent-width = 4 # Google Style Guide §3.4: 4 spaces 23 | 24 | target-version = "py312" # Minimum Python version 25 | 26 | [lint] 27 | ignore = [ 28 | "COM812", 29 | "FBT001", 30 | "FBT002", 31 | "D203", 32 | "D213", 33 | "ANN001", 34 | "ANN201", 35 | "ANN204", 36 | "D100", # Ignore Missing docstring in public module (often desired at top level __init__.py) 37 | "D102", # Ignore return type annotation in public method 38 | "D104", # Ignore Missing docstring in public package (often desired at top level __init__.py) 39 | "D107", # Ignore Missing docstring in __init__ (use class docstring) 40 | "TD002", # Ignore Missing author in TODOs (often not required) 41 | "TD003", # Ignore Missing issue link in TODOs (often not required/available) 42 | "T201", # Ignore print presence 43 | "RUF012", # Ignore Mutable class attributes should be annotated with `typing.ClassVar` 44 | "RUF013", # Ignore implicit optional 45 | ] 46 | 47 | select = [ 48 | "E", # pycodestyle errors (PEP 8) 49 | "W", # pycodestyle warnings (PEP 8) 50 | "F", # Pyflakes (logical errors, unused imports/variables) 51 | "I", # isort (import sorting - Google Style §3.1.2) 52 | "D", # pydocstyle (docstring conventions - Google Style §3.8) 53 | "N", # pep8-naming (naming conventions - Google Style §3.16) 54 | "UP", # pyupgrade (use modern Python syntax) 55 | "ANN",# flake8-annotations (type hint usage/style - Google Style §2.22) 56 | "A", # flake8-builtins (avoid shadowing builtins) 57 | "B", # flake8-bugbear (potential logic errors & style issues - incl. mutable defaults B006, B008) 58 | "C4", # flake8-comprehensions (unnecessary list/set/dict comprehensions) 59 | "ISC",# flake8-implicit-str-concat (disallow implicit string concatenation across lines) 60 | "T20",# flake8-print (discourage `print` - prefer logging) 61 | "SIM",# flake8-simplify (simplify code, e.g., `if cond: return True else: return False`) 62 | "PTH",# flake8-use-pathlib (use pathlib instead of os.path where possible) 63 | "PL", # Pylint rules ported to Ruff (PLC, PLE, PLR, PLW) 64 | "PIE",# flake8-pie (misc code improvements, e.g., no-unnecessary-pass) 65 | "RUF",# Ruff-specific rules (e.g., RUF001-003 ambiguous unicode) 66 | "RET",# flake8-return (consistency in return statements) 67 | "SLF",# flake8-self (check for private member access via `self`) 68 | "TID",# flake8-tidy-imports (relative imports, banned imports - configure if needed) 69 | "YTT",# flake8-boolean-trap (checks for boolean positional arguments, truthiness tests - Google Style §3.10) 70 | "TD", # flake8-todos (check TODO format - Google Style §3.7) 71 | ] 72 | 73 | exclude = [ 74 | ".bzr", 75 | ".direnv", 76 | ".eggs", 77 | ".git", 78 | ".hg", 79 | ".mypy_cache", 80 | ".nox", 81 | ".pants.d", 82 | ".pytype", 83 | ".ruff_cache", 84 | ".svn", 85 | ".tox", 86 | ".venv", 87 | "__pypackages__", 88 | "_build", 89 | "buck-out", 90 | "build", 91 | "dist", 92 | "node_modules", 93 | "venv", 94 | "*/migrations/*", 95 | ] 96 | 97 | [lint.isort] 98 | #force-sort-within-sections = true 99 | #combine-as-imports = true 100 | case-sensitive = true 101 | #force-single-line = false 102 | #known-first-party = [] 103 | #known-third-party = [] 104 | lines-after-imports = 2 105 | lines-between-types = 1 106 | #no-lines-before = ["LOCALFOLDER"] 107 | #required-imports = [] 108 | #section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"] 109 | 110 | [lint.pydocstyle] 111 | convention = "google" 112 | 113 | [lint.flake8-annotations] 114 | mypy-init-return = true 115 | allow-star-arg-any = false 116 | 117 | [lint.pep8-naming] 118 | ignore-names = ["test_*", "setUp", "tearDown", "mock_*"] 119 | classmethod-decorators = ["classmethod", "pydantic.validator", "pydantic.root_validator"] 120 | staticmethod-decorators = ["staticmethod"] 121 | 122 | [lint.flake8-tidy-imports] 123 | ban-relative-imports = "all" # Google generally prefers absolute imports (§3.1.2) 124 | 125 | [lint.flake8-quotes] 126 | docstring-quotes = "double" 127 | inline-quotes = "single" 128 | 129 | [lint.per-file-ignores] 130 | "__init__.py" = ["F401"] # Ignore unused imports in __init__.py 131 | "*_test.py" = ["D", "ANN"] # Ignore docstring and annotation issues in test files 132 | "test_*.py" = ["D", "ANN"] # Ignore docstring and annotation issues in test files 133 | 134 | [format] 135 | docstring-code-format = true 136 | docstring-code-line-length = "dynamic" # Or set to 80 137 | quote-style = "single" 138 | indent-style = "space" 139 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "[python]": { 4 | "editor.defaultFormatter": "charliermarsh.ruff", 5 | "editor.formatOnSave": true, 6 | "editor.codeActionsOnSave": { 7 | "source.organizeImports": "explicit" 8 | } 9 | }, 10 | "ruff.importStrategy": "fromEnvironment", 11 | "markdownlint.configFile": ".github/linters/.markdownlint.json" 12 | } 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [0.2.1](https://github.com/google-a2a/A2A/compare/v0.2.0...v0.2.1) (2025-05-27) 4 | 5 | ### Features 6 | 7 | * Add a new boolean for supporting authenticated extended cards ([#618](https://github.com/google-a2a/A2A/issues/618)) ([e0a3070](https://github.com/google-a2a/A2A/commit/e0a3070fc289110d43faf2e91b4ffe3c29ef81da)) 8 | * Add optional referenceTaskIds for task followups ([#608](https://github.com/google-a2a/A2A/issues/608)) ([5368e77](https://github.com/google-a2a/A2A/commit/5368e7728cb523caf1a9218fda0b1646325f524b)) 9 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of 9 | experience, education, socio-economic status, nationality, personal appearance, 10 | race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or reject 41 | comments, commits, code, wiki edits, issues, and other contributions that are 42 | not aligned to this Code of Conduct, or to ban temporarily or permanently any 43 | contributor for other behaviors that they deem inappropriate, threatening, 44 | offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | This Code of Conduct also applies outside the project spaces when the Project 56 | Steward has a reasonable belief that an individual's behavior may have a 57 | negative impact on the project or its community. 58 | 59 | ## Conflict Resolution 60 | 61 | We do not believe that all conflict is bad; healthy debate and disagreement 62 | often yield positive results. However, it is never okay to be disrespectful or 63 | to engage in behavior that violates the project’s code of conduct. 64 | 65 | If you see someone violating the code of conduct, you are encouraged to address 66 | the behavior directly with those involved. Many issues can be resolved quickly 67 | and easily, and this gives people more control over the outcome of their 68 | dispute. If you are unable to resolve the matter for any reason, or if the 69 | behavior is threatening or harassing, report it. We are dedicated to providing 70 | an environment where participants feel welcome and safe. 71 | 72 | Reports should be directed to *[PROJECT STEWARD NAME(s) AND EMAIL(s)]*, the 73 | Project Steward(s) for *[PROJECT NAME]*. It is the Project Steward’s duty to 74 | receive and address reported violations of the code of conduct. They will then 75 | work with a committee consisting of representatives from the Open Source 76 | Programs Office and the Google Open Source Strategy team. If for any reason you 77 | are uncomfortable reaching out to the Project Steward, please email 78 | opensource@google.com. 79 | 80 | We will investigate every complaint, but you may not receive a direct response. 81 | We will use our discretion in determining when and how to follow up on reported 82 | incidents, which may range from not taking action to permanent expulsion from 83 | the project and project-sponsored spaces. We will notify the accused of the 84 | report and provide them an opportunity to discuss it before any action is taken. 85 | The identity of the reporter will be omitted from the details of the report 86 | supplied to the accused. In potentially harmful situations, such as ongoing 87 | harassment or threats to anyone's safety, we may take action without notice. 88 | 89 | ## Attribution 90 | 91 | This Code of Conduct is adapted from the Contributor Covenant, version 1.4, 92 | available at 93 | https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 94 | 95 | Note: A version of this file is also available in the 96 | [New Project repo](https://github.com/google/new-project/blob/master/docs/code-of-conduct.md). 97 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | We'd love to accept your patches and contributions to this project. 4 | 5 | ## Before you begin 6 | 7 | ### Sign our Contributor License Agreement 8 | 9 | Contributions to this project must be accompanied by a 10 | [Contributor License Agreement](https://cla.developers.google.com/about) (CLA). 11 | You (or your employer) retain the copyright to your contribution; this simply 12 | gives us permission to use and redistribute your contributions as part of the 13 | project. 14 | 15 | If you or your current employer have already signed the Google CLA (even if it 16 | was for a different project), you probably don't need to do it again. 17 | 18 | Visit to see your current agreements or to 19 | sign a new one. 20 | 21 | ### Review our community guidelines 22 | 23 | This project follows 24 | [Google's Open Source Community Guidelines](https://opensource.google/conduct/). 25 | 26 | ## Contribution process 27 | 28 | ### Code reviews 29 | 30 | All submissions, including submissions by project members, require review. We 31 | use GitHub pull requests for this purpose. Consult 32 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 33 | information on using pull requests. 34 | 35 | ### Contributor Guide 36 | 37 | You may follow these steps to contribute: 38 | 39 | 1. **Fork the official repository.** This will create a copy of the official repository in your own account. 40 | 2. **Sync the branches.** This will ensure that your copy of the repository is up-to-date with the latest changes from the official repository. 41 | 3. **Work on your forked repository's feature branch.** This is where you will make your changes to the code. 42 | 4. **Commit your updates on your forked repository's feature branch.** This will save your changes to your copy of the repository. 43 | 5. **Submit a pull request to the official repository's main branch.** This will request that your changes be merged into the official repository. 44 | 6. **Resolve any linting errors.** This will ensure that your changes are formatted correctly. 45 | 46 | Here are some additional things to keep in mind during the process: 47 | 48 | - **Test your changes.** Before you submit a pull request, make sure that your changes work as expected. 49 | - **Be patient.** It may take some time for your pull request to be reviewed and merged. 50 | 51 | --- 52 | 53 | ## For Google Employees 54 | 55 | Complete the following steps to register your GitHub account and be added as a contributor to this repository. 56 | 57 | 1. Register your GitHub account at [go/GitHub](http://go/github) 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Agent2Agent (A2A) Protocol 2 | 3 | ![PyPI - Version](https://img.shields.io/pypi/v/a2a-sdk) 4 | [![Apache License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE) 5 | 6 | ![A2A Banner](docs/assets/a2a-banner.png) 7 | 8 | **An open protocol enabling communication and interoperability between opaque agentic applications.** 9 | 10 | The Agent2Agent (A2A) protocol addresses a critical challenge in the AI landscape: enabling gen AI agents, built on diverse frameworks by different companies running on separate servers, to communicate and collaborate effectively - as agents, not just as tools. A2A aims to provide a common language for agents, fostering a more interconnected, powerful, and innovative AI ecosystem. 11 | 12 | With A2A, agents can: 13 | 14 | - Discover each other's capabilities. 15 | - Negotiate interaction modalities (text, forms, media). 16 | - Securely collaborate on long running tasks. 17 | - Operate without exposing their internal state, memory, or tools. 18 | 19 | ## See A2A in Action 20 | 21 | Watch [this demo video](https://storage.googleapis.com/gweb-developer-goog-blog-assets/original_videos/A2A_demo_v4.mp4) to see how A2A enables seamless communication between different agent frameworks. 22 | 23 | ## Why A2A? 24 | 25 | As AI agents become more prevalent, their ability to interoperate is crucial for building complex, multi-functional applications. A2A aims to: 26 | 27 | - **Break Down Silos:** Connect agents across different ecosystems. 28 | - **Enable Complex Collaboration:** Allow specialized agents to work together on tasks that a single agent cannot handle alone. 29 | - **Promote Open Standards:** Foster a community-driven approach to agent communication, encouraging innovation and broad adoption. 30 | - **Preserve Opacity:** Allow agents to collaborate without needing to share internal memory, proprietary logic, or specific tool implementations, enhancing security and protecting intellectual property. 31 | 32 | ### Key Features 33 | 34 | - **Standardized Communication:** JSON-RPC 2.0 over HTTP(S). 35 | - **Agent Discovery:** Via "Agent Cards" detailing capabilities and connection info. 36 | - **Flexible Interaction:** Supports synchronous request/response, streaming (SSE), and asynchronous push notifications. 37 | - **Rich Data Exchange:** Handles text, files, and structured JSON data. 38 | - **Enterprise-Ready:** Designed with security, authentication, and observability in mind. 39 | 40 | ## Getting Started 41 | 42 | - 📚 **Explore the Documentation:** Visit the [Agent2Agent Protocol Documentation Site](https://goo.gle/a2a) for a complete overview, the full protocol specification, tutorials, and guides. 43 | - 📝 **View the Specification:** [A2A Protocol Specification](https://google-a2a.github.io/A2A/specification/) 44 | - 🐍 Use the [A2A Python SDK](https://github.com/google-a2a/a2a-python) 45 | - `pip install a2a-sdk` 46 | - 🎬 Use our [samples](https://github.com/google-a2a/a2a-samples) to see A2A in action 47 | 48 | ## Contributing 49 | 50 | We welcome community contributions to enhance and evolve the A2A protocol! 51 | 52 | - **Questions & Discussions:** Join our [GitHub Discussions](https://github.com/google-a2a/A2A/discussions). 53 | - **Issues & Feedback:** Report issues or suggest improvements via [GitHub Issues](https://github.com/google-a2a/A2A/issues). 54 | - **Contribution Guide:** See our [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute. 55 | - **Private Feedback:** Use this [Google Form](https://goo.gle/a2a-feedback). 56 | - **Partner Program:** Google Cloud customers can join our partner program via this [form](https://goo.gle/a2a-partner). 57 | 58 | ## What's next 59 | 60 | ### Protocol Enhancements 61 | 62 | - **Agent Discovery:** 63 | - Formalize inclusion of authorization schemes and optional credentials directly within the `AgentCard`. 64 | - **Agent Collaboration:** 65 | - Investigate a `QuerySkill()` method for dynamically checking unsupported or unanticipated skills. 66 | - **Task Lifecycle & UX:** 67 | - Support for dynamic UX negotiation _within_ a task (e.g., agent adding audio/video mid-conversation). 68 | - **Client Methods & Transport:** 69 | - Explore extending support to client-initiated methods (beyond task management). 70 | - Improvements to streaming reliability and push notification mechanisms. 71 | 72 | ## About 73 | 74 | The A2A Protocol is an open-source project by Google LLC, under the [Apache License 2.0](LICENSE), and is open to contributions from the community. 75 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | To report a security issue, please use [g.co/vulnz](https://g.co/vulnz). 4 | 5 | The Google Security Team will respond within 5 working days of your report on g.co/vulnz. 6 | 7 | We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue. 8 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # A2A Docs 2 | 3 | ## Published A2A docs 4 | 5 | [`https://google-a2a.github.io/A2A`](https://google-a2a.github.io/A2A) 6 | 7 | ## Developing A2A docs 8 | 9 | 1. Clone this repository and `cd` into the repository directory 10 | 2. Run `pip install -r requirements-docs.txt` 11 | 3. Run `mkdocs serve`, edit `.md` files, and live preview 12 | 4. Contribute docs changes as usual 13 | 14 | ## How it works 15 | 16 | - The A2A docs use [mkdocs](https://www.mkdocs.org/) and the 17 | [mkdocs-material theme](https://squidfunk.github.io/mkdocs-material/) 18 | - All of the source documentation / Markdown files related to the A2A docs are 19 | in the `docs/` directory in the A2A repository 20 | - `mkdocs.yml` in the repository root contains all of the docs config, including 21 | the site navigation and organization 22 | - There is a GitHub Action in `.github/workflows/docs.yml` that builds and 23 | publishes the docs and pushes the built assets to the `gh-pages` branch in 24 | this repository using `mkdocs gh-deploy --force`. This happens automatically for all 25 | commits / merges to `main`. 26 | - The A2A documentation is hosted in GitHub pages, and the settings for this are 27 | in the A2A repository settings in GitHub. 28 | -------------------------------------------------------------------------------- /docs/assets/a2a-actors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-a2a/A2A/2e889e25b7ef61079a381a46cb870b3fdd4b3e98/docs/assets/a2a-actors.png -------------------------------------------------------------------------------- /docs/assets/a2a-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-a2a/A2A/2e889e25b7ef61079a381a46cb870b3fdd4b3e98/docs/assets/a2a-banner.png -------------------------------------------------------------------------------- /docs/assets/a2a-logo-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/assets/a2a-logo-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/assets/a2a-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-a2a/A2A/2e889e25b7ef61079a381a46cb870b3fdd4b3e98/docs/assets/a2a-main.png -------------------------------------------------------------------------------- /docs/assets/a2a-mcp-readme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-a2a/A2A/2e889e25b7ef61079a381a46cb870b3fdd4b3e98/docs/assets/a2a-mcp-readme.png -------------------------------------------------------------------------------- /docs/assets/a2a-mcp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google-a2a/A2A/2e889e25b7ef61079a381a46cb870b3fdd4b3e98/docs/assets/a2a-mcp.png -------------------------------------------------------------------------------- /docs/community.md: -------------------------------------------------------------------------------- 1 | --- 2 | hide: 3 | - navigation 4 | --- 5 | 6 | # Welcome to the A2A Community 7 | 8 | The **Agent2Agent (A2A) protocol** is generating significant buzz across the 9 | tech world, and for good reason! This open interoperability protocol is designed 10 | to enable **seamless collaboration between AI agents across diverse frameworks 11 | and vendors**. By standardizing communication, A2A aims to unlock complex 12 | workflows, enhance productivity, and foster a new era of **"Agent 13 | Interoperability"**. Don't just take our word for it – see what the community is 14 | saying! 15 | 16 | ## The Word on the Street: Social Highlights 17 | 18 | The launch of A2A has sparked lively discussions and positive reactions on various social platforms. Here's a glimpse of the excitement: 19 | 20 | - **Rapid Interest and Adoption:** The A2A [GitHub repository](https://github.com/google-a2a/A2A) has seen an **explosive surge in popularity**. This rapid interest underscores the industry's eagerness for a standardized agent communication protocol, with many companies collaborating and contributing. 21 | 22 | - **Microsoft's interest via Semantic Kernel:** [Asha Sharma](https://www.linkedin.com/in/aboutasha/), Head of AI Platform Product at Microsoft, [announced on LinkedIn](https://www.linkedin.com/posts/aboutasha_a2a-ugcPost-7318649411704602624-0C_8) that "**Semantic Kernel now speaks A2A: a lightweight JSON-RPC protocol that lets agents swap context, not code or credentials, over plain HTTP. Drop it into your Foundry stack for instant, secure, async interoperability with any A2A-compliant agent, regardless of modality**". The post received numerous positive reactions, including "**A2A support in Semantic Kernel is a key unlock — context-level interoperability without sharing code or creds is how agent ecosystems scale securely across clouds**". 23 | 24 | - **Matt Pocock's Diagramming Intent:** [Matt Pocock](https://x.com/mattpocockuk), a well-known developer educator, [shared on X](https://x.com/mattpocockuk/status/1910002033018421400) "**I've just been reading the Agent2Agent technical docs - Google's new protocol for agent to agent communication. You know what that means. Let's diagram them:**". This tweet, liked and reposted hundreds of times, includes some great diagrams explaining the A2A protocol. 25 | 26 | - **Craig McLuckie's "Hot Take":** [Craig McLuckie](https://www.linkedin.com/in/craigmcluckie/) shared his initial thoughts on [LinkedIn](https://www.linkedin.com/posts/craigmcluckie_hot-take-on-agent2agent-vs-mcp-google-just-activity-7315939233792176128-4rGQ) "**Hot take on Agent2Agent vs MCP**". His post highlighted Google's careful positioning of A2A as focused on interactions _between_ agentic systems, rather than agents interacting with resources (the focus of MCP). This distinction is crucial for improving models' ability to understand expectations from other agents. McLuckie also pointed out the potential for A2A to enable systems to **advertise specific capabilities and specialities**, which is seen as "**sensible**". 27 | 28 | ## Community deep dive videos 29 | 30 | - [Zachary Huang](https://www.youtube.com/@ZacharyLLM) explains in his [YouTube video](https://www.youtube.com/watch?v=wrCF8MoXC_I), A2A "**complements**" MCP. While MCP acts as a "**USB-C port for AI applications**" connecting agents to tools, A2A acts as a communication standard **between the intelligent agents themselves**. This layered approach allows for building powerful systems where agents use A2A to coordinate and MCP to access necessary tools. 31 | - [Jack Herrington](https://www.youtube.com/@jherr) on his [YouTube video](https://www.youtube.com/watch?v=voaKr_JHvF4) walks through some of the provided examples and closes with his opinion that **"Having a specific protocol for agents to talk to other agents is valuable"** and reiterates, **"LLM plus tools are agents. MCP gives agents those tools. So that's why A2A and MCP play really nicely together**". 32 | - [Cole Medin](https://www.youtube.com/@ColeMedin) suggested on his [YouTube video](https://www.youtube.com/watch?v=ywMWpmOOaSo) that "**A2A was released very recently but it's already looking like it's going to follow a similar path**" to MCP in terms of growing interest. He also demonstrates the samples step by step and provides a summary of core concepts. 33 | - [Sam Witteveen](https://www.youtube.com/@samwitteveenai) covered A2A on his [YouTube video](https://www.youtube.com/watch?v=rAeqTaYj_aI) immediately after Google Cloud Next, discussing the value of making protocols open and not ending up with conflicting protocols. 34 | 35 | ## Community Contributions to A2A 36 | 37 | - Python Quickstart Tutorial [PR\#202](https://github.com/google-a2a/A2A/pull/202) 38 | - LlamaIndex submitted a sample implementation [PR\#179](https://github.com/google-a2a/A2A/pull/179) 39 | - Autogen sample server [PR\#232](https://github.com/google-a2a/A2A/pull/232) 40 | - AG2 \+ MCP example [PR\#230](https://github.com/google-a2a/A2A/pull/230) 41 | - PydanticAI example [PR\#127](https://github.com/google-a2a/A2A/pull/127) 42 | - Go example [PR\#52](https://github.com/google-a2a/A2A/pull/52) 43 | - Daytona sandbox running agent [PR\#170](https://github.com/google-a2a/A2A/pull/170) 44 | 45 | ## What is Driving This Excitement? 46 | 47 | The enthusiasm surrounding A2A stems from its potential to address key challenges in building sophisticated AI applications: 48 | 49 | - **Breaking Down Silos:** A2A aims to overcome the limitations of siloed AI systems by providing a **universal framework for agents built on different platforms to communicate and collaborate securely**. 50 | 51 | - **Enabling Complex Collaboration:** For tasks that require the expertise of multiple specialized agents, A2A provides a standardized way for them to **delegate tasks, exchange information, and coordinate actions**. This mirrors how human teams work together, distributing responsibilities for greater efficiency. 52 | 53 | - **Dynamic Agent Discovery:** A key feature of A2A is the ability for agents to **discover the capabilities of other agents** through standardized "**Agent Cards**". This dynamic discovery allows for more flexible and adaptable multi-agent systems. 54 | 55 | - **Complementary to MCP:** As stated on our [A2A ❤️ MCP topic page](topics/a2a-and-mcp.md) and affirmed by many community, A2A "**complements**" MCP. MCP acts as a communication standard between models and resources, providing tools for agents. A2A acts as a communication standard **between the intelligent agents themselves**. This layered approach allows for building powerful systems where agents use A2A to coordinate and MCP to access necessary tools. 56 | 57 | - **Open and Community-Driven:** Google has released A2A as **open source**, inviting contributions from the broader community to refine and expand its functionality. This commitment to open collaboration fosters innovation and broad adoption. 58 | 59 | ## The Future is Interoperable 60 | 61 | The social media buzz surrounding Google's A2A protocol clearly indicates a strong interest and belief in its potential to revolutionize the development of multi-agent AI systems. By providing a standardized way for AI agents to communicate and collaborate, A2A is poised to unlock new levels of automation, efficiency, and innovation. As enterprises increasingly adopt AI agents for a wide range of tasks, A2A represents a crucial step towards realizing the full power of interconnected AI ecosystems. 62 | 63 | Stay tuned for more updates and join the growing community building the future of AI interoperability with A2A! 64 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | hide: 3 | - navigation 4 | - toc 5 | --- 6 | 7 | # Agent2Agent (A2A) Protocol 8 | 9 | ![A2A Banner](assets/a2a-banner.png){width="70%"} 10 | {style="text-align: center; margin-bottom:1em; margin-top:1em;"} 11 | 12 | ## Unlock Collaborative Agent Scenarios 13 | 14 | The **Agent2Agent (A2A) Protocol** is an open standard designed to enable seamless communication and collaboration between AI agents. In a world where agents are built using diverse frameworks and by different vendors, A2A provides a common language, breaking down silos and fostering interoperability. 15 | 16 | - [Blog Post: Announcing the Agent2Agent Protocol (A2A)](https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/) 17 | - [Watch the A2A Demo Video](https://storage.googleapis.com/gweb-developer-goog-blog-assets/original_videos/A2A_demo_v4.mp4) 18 | 19 | ![A2A Main Graphic](assets/a2a-main.png){width="50%"} 20 | {style="text-align: center; margin-bottom:1em; margin-top:2em;"} 21 | 22 | --- 23 | 24 | ### Why A2A Matters 25 | 26 |
27 | 28 | - :material-account-group-outline:{ .lg .middle } **Interoperability** 29 | 30 | Connect agents built on different platforms (LangGraph, CrewAI, Semantic Kernel, custom solutions) to create powerful, composite AI systems. 31 | 32 | - :material-lan-connect:{ .lg .middle } **Complex Workflows** 33 | 34 | Enable agents to delegate sub-tasks, exchange information, and coordinate actions to solve complex problems that a single agent cannot. 35 | 36 | - :material-shield-key-outline:{ .lg .middle } **Secure & Opaque** 37 | 38 | Agents interact without needing to share internal memory, tools, or proprietary logic, ensuring security and preserving intellectual property. 39 | 40 |
41 | 42 | --- 43 | 44 | ### A2A and MCP: Complementary Protocols 45 | 46 | ![A2A MCP Graphic](assets/a2a-mcp-readme.png){width="60%"} 47 | {style="text-align: center; margin-bottom:1em; margin-top:1em;"} 48 | 49 | A2A and the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) are complementary standards for building robust agentic applications: 50 | 51 | - **MCP (Model Context Protocol):** Connects agents to **tools, APIs, and resources** with structured inputs/outputs. Think of it as the way agents access their capabilities. 52 | - **A2A (Agent2Agent Protocol):** Facilitates **dynamic, multimodal communication between different agents** as peers. It's how agents collaborate, delegate, and manage shared tasks. 53 | 54 | [Learn more about A2A and MCP](./topics/a2a-and-mcp.md) 55 | 56 | --- 57 | 58 | ### Get Started with A2A 59 | 60 |
61 | 62 | - :material-book-open:{ .lg .middle } **Read the Introduction** 63 | 64 | Understand the core ideas behind A2A. 65 | 66 | [:octicons-arrow-right-24: What is A2A?](./topics/what-is-a2a.md) 67 | 68 | [:octicons-arrow-right-24: Key Concepts](./topics/key-concepts.md) 69 | 70 | - :material-file-document-outline:{ .lg .middle } **Dive into the Specification** 71 | 72 | Explore the detailed technical definition of the A2A protocol. 73 | 74 | [:octicons-arrow-right-24: Protocol Specification](./specification.md) 75 | 76 | - :material-application-cog-outline:{ .lg .middle } **Follow the Tutorials** 77 | 78 | Build your first A2A-compliant agent with our step-by-step Python quickstart. 79 | 80 | [:octicons-arrow-right-24: Python Tutorial](./tutorials/python/1-introduction.md) 81 | 82 | - :material-code-braces:{ .lg .middle } **Explore Code Samples** 83 | 84 | See A2A in action with sample clients, servers, and agent framework integrations. 85 | 86 | [:fontawesome-brands-github: GitHub Samples](https://github.com/google-a2a/a2a-samples) 87 | 88 |
89 | -------------------------------------------------------------------------------- /docs/llms.txt: -------------------------------------------------------------------------------- 1 | # A2A (Agent2Agent) Protocol High-Level Summary 2 | 3 | This project defines and demonstrates the **Agent2Agent (A2A) protocol**, an open standard initiated by Google designed to enable communication and interoperability between disparate AI agent systems. The core goal is to allow agents built on different frameworks (e.g., LangGraph, CrewAI, Google ADK, Genkit) or by different vendors to discover each other's capabilities, negotiate interaction modes (text, forms, files, potentially audio/video later), and collaborate on tasks. 4 | 5 | The repository provides: 6 | 7 | 1. **Formal Specification:** A detailed JSON Schema (`specification/json/a2a.json`) defining the structure of A2A messages, including requests, responses, task states, artifacts, and agent metadata (Agent Cards). 8 | 2. **Core Concepts Documentation (Implied):** Links in the main README suggest documentation covering agent discovery, task lifecycle, artifact exchange, streaming updates, push notifications, and enterprise readiness. 9 | 3. **Sample Implementations:** 10 | - **Common Libraries:** Reusable Python (`samples/python/common`) and JavaScript/TypeScript (`samples/js/src`) code for building A2A clients and servers, handling JSON-RPC communication, task management, and potentially authentication. 11 | - **Example Agents:** Demonstrations of integrating A2A into various agent frameworks: 12 | - **Python:** LangGraph (currency conversion, streaming), CrewAI (image generation, file artifacts), Google ADK (expense reports, form handling). 13 | - **JavaScript/TypeScript:** Genkit (movie info via API, code generation with file artifacts). 14 | - **Example Hosts:** Applications that *consume* A2A services: 15 | - CLIs in both Python and JS for direct interaction. 16 | - A Python-based multi-agent orchestrator (using Google ADK) that delegates tasks to other A2A agents. 17 | 4. **Demo Web Application:** A web UI (`demo/ui`, likely using Mesop) demonstrating multi-agent interactions facilitated by the A2A protocol, including visualization of conversations, tasks, events, and agent discovery. It features a backend service coordinating with the host agent. 18 | 19 | Key features of the A2A protocol highlighted by the specification and samples include: agent discovery via Agent Cards, standardized task management (send, get, cancel), support for different content types (text, files, structured data) via `Parts` and `Artifacts`, streaming updates for long-running tasks, and mechanisms for push notifications. The project is open source and encourages community contribution. 20 | 21 | # A2A (Agent2Agent) Protocol 22 | 23 | ## 1. Overview 24 | 25 | - **Project Name:** Agent2Agent (A2A) Protocol 26 | - **Purpose:** An open protocol by Google enabling communication and interoperability between AI agents built on different frameworks or by different vendors. 27 | - **Core Goal:** Allow agents to discover capabilities, negotiate interaction, and collaborate securely on tasks. 28 | - **Communication:** Uses JSON-RPC 2.0 over HTTP(S). Supports standard request/response and Server-Sent Events (SSE) for streaming. 29 | - **Key Components:** Specification (JSON Schema), Common Libraries (Python, JS/TS), Sample Agents (LangGraph, CrewAI, ADK, Genkit), Sample Hosts (CLI, Orchestrator), Demo Web App (Mesop). 30 | 31 | ## 2. Protocol Specification (`specification/json/a2a.json`) 32 | 33 | ### 2.1. Core JSON-RPC Structures 34 | 35 | - **`JSONRPCMessage`:** Base for requests/responses. Contains `jsonrpc: "2.0"` and optional `id`. 36 | - **`JSONRPCRequest`:** Represents a request. 37 | - `method`: String identifying the operation (e.g., "tasks/send"). 38 | - `params`: Object or Array containing parameters for the method. 39 | - `id`: Unique identifier (string/number) for request/response correlation. Omitted/null for notifications. 40 | - **`JSONRPCResponse`:** Represents a response. 41 | - `result`: Contains the successful result data (can be `null`). Mutually exclusive with `error`. 42 | - `error`: Contains an error object if the request failed. Mutually exclusive with `result`. 43 | - `id`: Must match the corresponding request `id`. 44 | - **`JSONRPCError`:** Represents an error. 45 | - `code`: Integer error code. 46 | - `message`: String description of the error. 47 | - `data`: Optional additional error details. 48 | 49 | ### 2.2. Key A2A Data Objects 50 | 51 | - **`AgentCard`:** Metadata describing an agent. Found typically at `/.well-known/agent.json`. 52 | - `name`: (string) Human-readable name. 53 | - `description`: (string) Agent description. 54 | - `url`: (string) Base URL endpoint for the agent's A2A service. 55 | - `provider`: (`AgentProvider`) Organization details (optional). 56 | - `version`: (string) Agent/API version. 57 | - `documentationUrl`: (string) Link to documentation (optional). 58 | - `capabilities`: (`AgentCapabilities`) Features supported (streaming, push). 59 | - `securitySchemes`: (Object) Security scheme details for authentication (optional). 60 | - `security`: (Array) Security requirements for contacting the agent (optional). 61 | - `defaultInputModes`: (string[]) Default supported input types (e.g., "text/plain", "application/json"). 62 | - `defaultOutputModes`: (string[]) Default supported output types. 63 | - `skills`: (`AgentSkill[]`) List of specific capabilities. 64 | - `supportsAuthenticatedExtendedCard`: (boolean) Indicates support for retrieving a more detailed Agent Card via an authenticated endpoint (optional). 65 | - **`AgentCapabilities`:** 66 | - `streaming`: (boolean) Supports `message/stream` and `tasks/resubscribe` for real-time updates via Server-Sent Events (SSE). Default: `false`. 67 | - `pushNotifications`: (boolean) Supports `tasks/pushNotificationConfig/set|get` for asynchronous task updates via webhooks. Default: `false`. 68 | - `stateTransitionHistory`: (boolean) Supports providing detailed history of status changes within the Task object (future enhancement). Default: `false`. 69 | - **`AgentSkill`:** 70 | - `id`: (string) Unique skill ID within this agent. 71 | - `name`: (string) Human-readable skill name. 72 | - `description`: (string) Detailed skill description. CommonMark may be used. 73 | - `tags`: (string[]) Keywords/categories for discoverability. 74 | - `examples`: (string[]) Example prompts or use cases demonstrating skill usage (optional). 75 | - `inputModes`: (string[]) Overrides `defaultInputModes` for this specific skill. Accepted Media Types (optional). 76 | - `outputModes`: (string[]) Overrides `defaultOutputModes` for this specific skill. Produced Media Types (optional). 77 | - **`Task`:** Represents a unit of work processed by an agent. 78 | - `id`: (string) Unique task identifier. 79 | - `contextId`: (string) Groups related tasks in a conversation or session. 80 | - `status`: (`TaskStatus`) Current state information. 81 | - `artifacts`: (`Artifact[]`) Files/data produced by the agent (optional). 82 | - `history`: (`TaskStatus[]`) Status transition history (optional, requires `stateTransitionHistory` capability). 83 | - `metadata`: (object) Custom key-value data for client use (optional). 84 | - `kind`: ("task") Type discriminator. 85 | - **`TaskStatus`:** 86 | - `state`: (`TaskState`) Current lifecycle state (enum). 87 | - `message`: (string) Human-readable status message (optional). 88 | - `timestamp`: (string) ISO-8601 timestamp of when this status was set. 89 | - `kind`: ("status") Type discriminator. 90 | - **`TaskState`:** (enum) 91 | - `submitted`: Task received but not yet processing (non-terminal). 92 | - `working`: Task is actively being processed (non-terminal). 93 | - `input_required`: Task requires additional input from the client to proceed (non-terminal). 94 | - `completed`: Task completed successfully (terminal). 95 | - `failed`: Task encountered an error (terminal). 96 | - `canceled`: Task was canceled by client request (terminal). 97 | - `rejected`: Task was rejected by the agent (terminal). 98 | - `auth-required`: Authentication required from client/user to proceed (non-terminal). 99 | - `unknown`: Task state cannot be determined (terminal). 100 | - **`Message`:** Communication unit between user and agent. 101 | - `role`: ("user" | "agent") Sender role. 102 | - `parts`: (`Part[]`) Content parts (text, file, data). 103 | - `metadata`: (object | null) Message-specific metadata. 104 | - `messageId`: (string) Unique identifier for the message. 105 | - `parentMessageId`: (string) Reference to a previous message being replied to (optional). 106 | - `rootMessageId`: (string) Reference to the first message in a thread (optional). 107 | - `referenceTaskIds`: (string[]) List of tasks referenced as contextual hint by this message (optional). 108 | - `taskId`: (string) Task identifier the current message is related to (optional). 109 | - `contextId`: (string) Context identifier the message is associated with (optional). 110 | - `kind`: ("message") Type discriminator. 111 | - **`Part` (Union Type):** Represents a piece of content within a Message or Artifact. 112 | - **`TextPart`:** 113 | - `type`: "text" 114 | - `text`: (string) Text content. 115 | - `mimeType`: (string) Format specification (default: "text/plain"). 116 | - **`FilePart`:** 117 | - `type`: "file" 118 | - `file`: (`FileWithUri`) File reference with URI. 119 | - `inline`: (boolean) Whether the file content should be displayed inline (optional). 120 | - **`DataPart`:** 121 | - `type`: "data" 122 | - `data`: (any) Structured data in JSON-serializable format. 123 | - `mimeType`: (string) Format specification (e.g., "application/json"). 124 | - `inline`: (boolean) Whether the data should be displayed inline (optional). 125 | - `metadata`: (object | null) Optional metadata for the specific part. 126 | - **`FileWithUri`:** Represents a file reference with URI. 127 | - `name`: (string) Filename with extension. 128 | - `mimeType`: (string) Content type (Media Type). 129 | - `uri`: (string) URI to access the file content. 130 | - **`Artifact`:** An output generated by a task. 131 | - `artifactId`: (string) Unique identifier for the artifact. 132 | - `name`: (string) Human-readable artifact name (optional). 133 | - `description`: (string) Detailed description of the artifact (optional). 134 | - `parts`: (`Part[]`) Content segments in the artifact. 135 | - `metadata`: (object) Custom key-value data (optional). 136 | - `kind`: ("artifact") Type discriminator. 137 | - **`AuthenticationInfo`:** Authentication details for push notifications. 138 | - `schemes`: (string[]) Array of authentication scheme names the caller must use. 139 | - `credentials`: (string) Optional static credentials or scheme-specific configuration info. 140 | - **`PushNotificationConfig`:** Configuration for push notifications. 141 | - `url`: (string) Endpoint URL for the agent to POST notifications to. 142 | - `token`: (string) Optional authentication token for the agent to include in requests (optional). 143 | - `authentication`: (`AuthenticationInfo`) Authentication details the agent needs to call the URL (optional). 144 | - **`TaskPushNotificationConfig`:** Associates a `PushNotificationConfig` with a task ID. 145 | - `taskId`: (string) The task ID to receive push notifications for. 146 | - `config`: (`PushNotificationConfig`) The push notification configuration to use. 147 | - `metadata`: (object) Custom key-value data for client use (optional). 148 | - **`MessageSendParams`:** Parameters for sending a message. 149 | - `message`: (`Message`) The message to send. 150 | - `configuration`: (`MessageSendConfiguration`) Optional configuration for the message. 151 | - `metadata`: (object) Custom key-value data for client use (optional). 152 | - **`agent/authenticatedExtendedCard`:** (HTTP GET) 153 | - Retrieves a potentially more detailed version of the Agent Card after the client has authenticated. 154 | - Available only if `AgentCard.supportsAuthenticatedExtendedCard` is `true`. 155 | - Endpoint URL: `{AgentCard.url}/../agent/authenticatedExtendedCard` 156 | - Authentication: Required using one of the schemes declared in the public `AgentCard.securitySchemes`. 157 | - Response: Complete `AgentCard` object with potentially additional details. 158 | 159 | ### 2.3. A2A RPC Methods 160 | 161 | - **`message/send`:** (Request/Response) 162 | - Sends a message to initiate or continue a task. 163 | - `params`: `MessageSendParams` (includes `taskId`, `contextId`, `message`, optionally `configuration`). 164 | - `result`: `Task` (final state after synchronous processing). 165 | - **`message/stream`:** (Request/Stream) 166 | - Sends a message and subscribes to real-time updates via Server-Sent Events (SSE). 167 | - `params`: `MessageSendParams`. 168 | - `result` (stream events): `SendStreamingMessageResponse` containing one of: `MessageEvent`, `TaskStatusUpdateEvent`, `TaskArtifactUpdateEvent`. Final event has `final: true`. 169 | - **`tasks/get`:** (Request/Response) 170 | - Retrieves the current state of a task. 171 | - `params`: `TaskQueryParams` (includes `id`, optionally `historyLength`). 172 | - `result`: `Task`. 173 | - **`tasks/cancel`:** (Request/Response) 174 | - Requests cancellation of a running task. 175 | - `params`: `TaskIdParams` (includes `id`). 176 | - `result`: `Task` (updated state, likely 'canceled') or error if not cancelable. 177 | - **`tasks/pushNotificationConfig/set`:** (Request/Response) 178 | - Sets or updates the push notification configuration for a task. 179 | - `params`: `TaskPushNotificationConfig`. 180 | - `result`: `TaskPushNotificationConfig` (confirmed configuration). 181 | - **`tasks/pushNotificationConfig/get`:** (Request/Response) 182 | - Retrieves the current push notification configuration for a task. 183 | - `params`: `TaskIdParams` (includes `taskId`). 184 | - `result`: `TaskPushNotificationConfig`. 185 | - **`tasks/resubscribe`:** (Request/Stream) 186 | - Resubscribes to task updates after a connection interruption (SSE). 187 | - `params`: `TaskQueryParams`. 188 | - `result` (stream events): `TaskStatusUpdateEvent` or `TaskArtifactUpdateEvent`. 189 | 190 | ### 2.4. Streaming Update Events (Result of `message/stream` or `tasks/resubscribe`) 191 | 192 | - **`SendStreamingMessageResponse`:** Contains a message from the agent. 193 | - `type`: "message" 194 | - `message`: (`Message`) The message content. 195 | - `contextId`: (string) Context identifier the message is associated with. 196 | - `kind`: ("streaming-response") Type discriminator. 197 | - `final`: (boolean) True if this is the final message for the task. 198 | - **`TaskStatusUpdateEvent`:** Signals a change in task status. 199 | - `type`: "task-status" 200 | - `taskId`: (string) Task ID. 201 | - `contextId`: (string) Context identifier the task is associated with. 202 | - `kind`: ("status-update") Type discriminator. 203 | - `status`: (`TaskStatus`) The new status object. 204 | - `final`: (boolean) True if this is the terminal update for the task. 205 | - **`TaskArtifactUpdateEvent`:** Signals a new or updated artifact. 206 | - `type`: "task-artifact" 207 | - `taskId`: (string) Task ID. 208 | - `artifact`: (`Artifact`) The artifact data. 209 | - `append`: (boolean) If true, append parts to artifact; if false (default), replace. 210 | - `lastChunk`: (boolean) If true, indicates this is the final update for the artifact. 211 | - `final`: (boolean) Usually false for artifacts, can signal end concurrently with status. 212 | 213 | ### 2.5. Standard Error Codes 214 | 215 | - `-32700`: `JSONParseError` - Invalid JSON payload. 216 | - `-32600`: `InvalidRequestError` - Invalid JSON-RPC request object. 217 | - `-32601`: `MethodNotFoundError` - Method does not exist. 218 | - `-32602`: `InvalidParamsError` - Invalid method parameters. 219 | - `-32603`: `InternalError` - Internal server error. 220 | 221 | ### 2.6. A2A Specific Error Codes 222 | 223 | - `-32001`: `TaskNotFoundError` - Specified task ID not found. 224 | - `-32002`: `TaskNotCancelableError` - Task is in a terminal state and cannot be canceled. 225 | - `-32003`: `PushNotificationNotSupportedError` - Agent does not support push notifications. 226 | - `-32004`: `UnsupportedOperationError` - The requested operation is not supported. 227 | - `-32005`: `ContentTypeNotSupportedError` - Mismatch in supported content types. 228 | - `-32006`: `InvalidAgentResponseError` - Agent generated an invalid response for the requested method. 229 | 230 | ## 3. Core Concepts 231 | 232 | - **Agent Discovery:** Clients find agents and their capabilities by fetching the `AgentCard` JSON, typically from `/.well-known/agent.json`. 233 | - **Task Lifecycle:** Tasks progress through states defined in `TaskState` (submitted -> working -> [input_required] -> completed/failed/canceled/rejected/unknown). 234 | - **Communication:** Uses `Message` objects containing `Part`s (text, file, data). Task outputs are represented as `Artifact`s, also containing `Part`s. 235 | - **Streaming:** Long-running tasks can provide real-time updates using Server-Sent Events (SSE) via `message/stream`. Updates are sent as `MessageEvent`, `TaskStatusUpdateEvent` and `TaskArtifactUpdateEvent`. Reconnection after interruptions is supported via `tasks/resubscribe`. 236 | - **Push Notifications:** Agents can proactively notify clients about task updates using webhook URLs provided via `tasks/pushNotificationConfig/set`. Authentication mechanisms (e.g., Bearer tokens via JWT signed with keys from agent's JWKS endpoint) are supported for secure communication. 237 | - **Authentication:** Defined in `AgentCard` (via `securitySchemes` and `security` fields) and `PushNotificationConfig`. Can involve various schemes (e.g., API keys, OAuth, JWT). The protocol supports authenticated extended Agent Card retrieval via the `agent/authenticatedExtendedCard` endpoint. Samples use JWT for push notifications and secure communication. 238 | - **Forms:** Structured data can be requested and submitted using `DataPart` within Messages/Artifacts (demonstrated in ADK sample). 239 | 240 | ## 4. Security Considerations 241 | 242 | - **Transport Security:** Always use HTTPS with strong TLS configurations in production environments. 243 | - **Authentication:** 244 | - Handled via standard HTTP mechanisms (e.g., `Authorization` header with Bearer tokens, API keys). 245 | - Requirements are declared in the `AgentCard`. 246 | - Credentials MUST be obtained out-of-band by the client. 247 | - A2A Servers MUST authenticate every request. 248 | - **Authorization:** 249 | - A server-side responsibility based on the authenticated identity. 250 | - Implement the principle of least privilege. 251 | - Can be granular, based on skills, actions, or data. 252 | - **Push Notification Security:** 253 | - Webhook URL validation (by the A2A Server sending notifications) is crucial to prevent SSRF. 254 | - Authentication of the A2A Server to the client's webhook is essential. 255 | - Authentication of the notification by the client's webhook receiver (verifying it came from the legitimate A2A Server and is relevant) is critical. 256 | - **Input Validation:** Servers MUST rigorously validate all RPC parameters and the content/structure of data in `Message` and `Artifact` parts to prevent injection attacks or processing errors. 257 | - **Resource Management:** Implement rate limiting, concurrency controls, and resource limits to protect agents from abuse or overload. 258 | - **Data Privacy:** Adhere to all applicable privacy regulations for data exchanged in `Message` and `Artifact` parts. Minimize sensitive data transfer. 259 | 260 | ## 4. Implementations & Samples 261 | 262 | ### 4.1. Common Libraries 263 | 264 | - **Python (`samples/python/common`)**: 265 | - `client/`: `A2AClient` for making requests, `A2ACardResolver` for discovery. 266 | - `server/`: `A2AServer` (Starlette-based), `TaskManager` base class, `InMemoryTaskManager`. 267 | - `types.py`: Pydantic models mirroring the JSON schema. 268 | - `utils/`: Helpers for push notification auth (JWT signing/verification, JWKS endpoint). 269 | - **JavaScript/TypeScript (`samples/js/src`)**: 270 | - `client/`: `A2AClient` implementation using `fetch`. 271 | - `server/`: `A2AServer` (Express-based), `TaskStore` interface, `InMemoryTaskStore`, `FileStore`. 272 | - `schema.ts`: TypeScript interfaces matching the JSON schema. 273 | - `handler.ts`, `error.ts`, `utils.ts`: Support code for the server. 274 | 275 | ### 4.2. Python Samples 276 | 277 | - **Location:** `samples/python/agents/` & `samples/python/hosts/` 278 | - **Setup:** Uses `uv` and `pyproject.toml`. Requires Python >= 3.12/3.13. API keys via `.env`. 279 | - **Agents:** 280 | - **LangGraph (`agents/langgraph`)**: Currency conversion agent. Demonstrates tool use, multi-turn (`input-required`), and **streaming** (`tasks/sendSubscribe`). 281 | - **CrewAI (`agents/crewai`)**: Image generation agent. Demonstrates multi-turn and handling **file artifacts** (images). 282 | - **Google ADK (`agents/google_adk`)**: Expense reimbursement agent. Demonstrates multi-turn and handling **forms** using `DataPart`. 283 | - **Hosts:** 284 | - **CLI (`hosts/cli`)**: Simple command-line client to interact with any A2A agent. Supports streaming and optional push notification listening. 285 | - **Multi-Agent Orchestrator (`hosts/multiagent`)**: An ADK-based "Host Agent" that manages connections (`RemoteAgentConnections`) to other A2A agents and delegates tasks based on instructions. 286 | 287 | ### 4.3. JavaScript/TypeScript Samples 288 | 289 | - **Location:** `samples/js/` 290 | - **Setup:** Uses `npm`/`pnpm`, `tsx`, `tsconfig.json`. Requires Node.js >= 18. API keys via environment variables. Framework: **Genkit**. 291 | - **Agents (`src/agents/`)**: 292 | - **Movie Agent (`movie-agent`)**: Uses TMDB API via Genkit tools to answer movie questions. Demonstrates tool use and multi-turn (`AWAITING_USER_INPUT` mapped to `input-required`). 293 | - **Coder Agent (`coder`)**: Generates code files. Demonstrates producing multiple **file artifacts** via streaming updates. Uses custom Genkit format (`code-format.ts`). 294 | - **Hosts:** 295 | - **CLI (`src/cli.ts`)**: Command-line client for interacting with JS agents. 296 | 297 | ### 4.4. Demo Application (`demo/`) 298 | 299 | - **UI (`demo/ui`)**: Web application built with **Mesop**. 300 | - Visualizes conversations with multiple agents via the host orchestrator. 301 | - Renders text, images, forms. 302 | - Allows dynamic agent registration via URL. 303 | - Provides views for task list and event logs. 304 | - **Service (`demo/ui/service`)**: Backend service for the Mesop UI. 305 | - `server/`: Manages conversations, routes messages, interfaces with the host agent (`ADKHostManager` or `InMemoryFakeAgentManager`). 306 | - `client/`: Client used by the UI to talk to its *own* backend service. 307 | 308 | ## 5. Development & Setup 309 | 310 | - **Prerequisites:** Python (>=3.12 or 3.13), Node.js (>=18), `uv` (for Python), `npm`/`pnpm` (for JS). 311 | - **API Keys:** Required for LLM access (e.g., `GOOGLE_API_KEY`, `TMDB_API_KEY`), typically set via `.env` files or environment variables. 312 | - **Running Samples:** Generally involves running an agent server (`uv run ...` or `npm run ...`) and then a host client/app (e.g., `uv run hosts/cli --agent `). 313 | 314 | ## 6. Contribution 315 | 316 | - See `CONTRIBUTING.md`. 317 | - GitHub discussion available as the primary means of communication. 318 | - GitHub issues for bugs and feature requests. 319 | - Google Form for private feedback. 320 | -------------------------------------------------------------------------------- /docs/partners.md: -------------------------------------------------------------------------------- 1 | --- 2 | hide: 3 | - navigation 4 | --- 5 | 6 | # Partners 7 | 8 | Below is a list of partners (and a link to their A2A announcement or blog post, 9 | if available) who are part of the A2A community and are helping build, codify, 10 | and adopt A2A as the standard protocol for AI agents to communicate and 11 | collaborate effectively with each other and with users. 12 | 13 | !!! note 14 | 15 | If you're interested in becoming a partner of A2A and getting your listing added to or updated on this page, let us know by [submitting this form](https://forms.gle/BuQQ2zvXfFUA1bu98), and we'll contact you soon! 16 | 17 | - [Accelirate Inc](https://www.accelirate.com) 18 | - [Accenture](https://www.accenture.com) 19 | - [Activeloop](https://www.activeloop.ai/) 20 | - [Adobe](https://www.adobe.com) 21 | - [AI21 Labs](https://www.ai21.com/) 22 | - [AI71](https://ai71.ai/) 23 | - [Aisera](https://aisera.com/) 24 | - [Almawave.it](http://www.almawave.it) 25 | - [AliCloud](http://www.alibabacloud.com) 26 | - [ArcBlock](http://www.arcblock.io) 27 | - [Arize](https://arize.com/blog/arize-ai-and-future-of-agent-interoperability-embracing-googles-a2a-protocol/) 28 | - [Articul8](https://www.articul8.ai/news/unleashing-the-next-frontier-of-enterprise-ai-introducing-model-mesh-dock-and-inter-lock-and-our-a2-a-partnership-with-google) 29 | - [ask-ai.com](https://ask-ai.com) 30 | - [Atlassian](https://www.atlassian.com) 31 | - [Auth0](https://auth0.com/blog/auth0-google-a2a/) 32 | - [Autodesk](https://www.autodesk.com) 33 | - [Beekeeper](http://beekeeper.io) 34 | - [BCG](https://www.bcg.com) 35 | - [Block Inc](https://block.xyz/) 36 | - [Bloomberg LP](http://techatbloomberg.com/) 37 | - [BLUEISH Inc](https://www.blueish.co.jp/) 38 | - [BMC Software Inc](https://www.bmc.com/it-solutions/bmc-helix.html) 39 | - [Boomi](https://boomi.com/) 40 | - [Box](https://www.box.com) 41 | - [Bridge2Things Automation Process GmbH](http://bridge2things.at) 42 | - [Cafe 24](https://www.cafe24corp.com/en/company/about) 43 | - [C3 AI](https://c3.ai) 44 | - [Capgemini](https://www.capgemini.com) 45 | - [Chronosphere](https://chronosphere.io) 46 | - [Codimite PTE LTD](https://codimite.ai/) 47 | - [Cognigy](https://www.cognigy.com/) 48 | - [Cognizant](https://www.cognizant.com) 49 | - [Cohere](https://cohere.com) 50 | - [Collibra](https://www.collibra.com) 51 | - [Confluent](https://developer.confluent.io) 52 | - [Contextual](https://contextual.ai) 53 | - [Cotality](https://cotality.com) (fka Corelogic) 54 | - [Crubyt](https://www.crubyt.com) 55 | - [Cyderes](http://www.cyderes.com) 56 | - [Datadog](https://www.datadoghq.com) 57 | - [DataRobot](https://www.datarobot.com) 58 | - [DataStax](https://www.datastax.com) 59 | - [Decagon.ai](https://decagon.ai) 60 | - [Deloitte](https://www.prnewswire.com/news-releases/deloitte-expands-alliances-with-google-cloud-and-servicenow-to-accelerate-agentic-ai-adoption-in-the-enterprise-302423941.html) 61 | - [Devnagri](https://devnagri.com) 62 | - [Deutsche Telekom](https://www.telekom.com/en) 63 | - [Dexter Tech Labs](http://www.dextertechlabs.com) 64 | - [Distyl.ai](https://distyl.ai) 65 | - [Elastic](https://www.elastic.co) 66 | - [Ema.co](https://ema.co) 67 | - [EPAM](https://www.epam.com) 68 | - [Eviden (Atos Group)](https://atos.net/) 69 | - [fractal.ai](https://fractal.ai/new) 70 | - [GenAI Nebula9.ai Solutions Pvt Ltd](http://nebula9.ai) 71 | - [Glean](https://www.glean.com) 72 | - [Global Logic](https://www.globallogic.com/) 73 | - [Gravitee](https://www.gravitee.io/) 74 | - [GrowthLoop](https://growthloop.com) 75 | - [Guru](http://www.getguru.com) 76 | - [Harness](https://harness.io) 77 | - [HCLTech](https://www.hcltech.com) 78 | - [Headwaters](https://www.headwaters.co.jp) 79 | - [Hellotars](https://hellotars.com) 80 | - [Hexaware](https://hexaware.com/) 81 | - [HUMAN](https://www.humansecurity.com/) 82 | - [Incorta](https://www.incorta.com) 83 | - [InfoSys](https://www.infosys.com) 84 | - [Intuit](https://www.intuit.com) 85 | - [Iron Mountain](https://www.ironmountain.com/) 86 | - [JetBrains](https://www.jetbrains.com) 87 | - [JFrog](https://jfrog.com) 88 | - [King's College London](https://www.kcl.ac.uk/informatics) 89 | - [KPMG](https://kpmg.com/us/en/media/news/kpmg-google-cloud-alliance-expansion-agentspace-adoption.html) 90 | - [Kyndryl](http://www.kyndryl.com) 91 | - [LabelBox](https://labelbox.com) 92 | - [LangChain](https://www.langchain.com) 93 | - [LG CNS](http://www.lgcns.com) 94 | - [Livex.ai](https://livex.ai) 95 | - [LlamaIndex](https://x.com/llama_index/status/1912949446322852185) 96 | - [LTIMindTtree](https://www.ltimindtree.com) 97 | - [Lumeris](https://www.lumeris.com/) 98 | - [Lyzr.ai](https://lyzr.ai) 99 | - [Magyar Telekom](https://www.telekom.hu/) 100 | - [Microsoft](https://www.microsoft.com/en-us/microsoft-cloud/blog/2025/05/07/empowering-multi-agent-apps-with-the-open-agent2agent-a2a-protocol/) 101 | - [McKinsey](https://www.mckinsey.com) 102 | - [MongoDB](https://www.mongodb.com) 103 | - [Neo4j](https://neo4j.com) 104 | - [New Relic](https://newrelic.com) 105 | - [Nisum](http://www.nisum.com) 106 | - [Noorle Inc](http://www.noorle.com) 107 | - [Optimizely Inc](https://www.optimizely.com/) 108 | - [Oracle / NetSuite](https://www.oracle.com/netsuite) 109 | - [PancakeAI](https://www.pancakeai.tech/) 110 | - [Pendo](https://www.pendo.io) 111 | - [PerfAI.ai](https://perfai.ai) 112 | - [Personal AI](https://personal.ai) 113 | - [Productive Edge](https://www.productiveedge.com/) 114 | - [Proofs](https://proofs.io) 115 | - [Publicis Sapient](https://www.publicissapient.com/) 116 | - [PWC](https://www.pwc.com) 117 | - [Quantiphi](https://www.quantiphi.com) 118 | - [Radix](https://radix.website/) 119 | - [RagaAI Inc](https://raga.ai/) 120 | - [Red Hat](https://www.redhat.com) 121 | - [Reltio Inc](http://www.reltio.com) 122 | - [S&P](https://www.spglobal.com) 123 | - [Sage](https://www.sage.com/en-us/) 124 | - [Salesforce](https://www.salesforce.com) 125 | - [SAP](https://news.sap.com/2025/04/sap-google-cloud-enterprise-ai-open-agent-collaboration-model-choice-multimodal-intelligence/) 126 | - [Sayone Technologies](https://www.sayonetech.com/) 127 | - [ServiceNow](https://www.servicenow.com) 128 | - [Siemens AG](https://siemens.com/) 129 | - [SoftBank Corp](https://www.softbank.jp/en//) 130 | - [Solace](https://solace.com/products/agent-mesh/) 131 | - [Stacklok, Inc](https://stacklok.com) 132 | - [Supertab](https://www.supertab.co/post/supertab-connect-partners-with-google-cloud-to-enable-ai-agents) 133 | - [Suzega](https://suzega.com/) 134 | - [TCS](https://www.tcs.com) 135 | - [Tech Mahindra](https://www.techmahindra.com/) 136 | - [Test Innovation Technology](https://www.test-it.com) 137 | - [the artinet project](https://artinet.io/) 138 | - [Think41](http://www.think41.com) 139 | - [Thoughtworks](https://www.thoughtworks.com/) 140 | - [Tredence](http://www.tredence.com) 141 | - [Two Tall Totems Ltd. DBA TTT Studios](https://ttt.studio) 142 | - [Typeface](https://typeface.ai) 143 | - [UKG](https://www.ukg.com) 144 | - [UiPath](https://www.uipath.com/newsroom/uipath-launches-first-enterprise-grade-platform-for-agentic-automation) 145 | - [Upwork, Inc.](https://www.upwork.com/) 146 | - [Ushur, Inc.](http://ushur.ai) 147 | - [Valle AI](http://www.valleai.com.br) 148 | - [Valtech](https://www.valtech.com/) 149 | - [Vervelo](https://www.vervelo.com/) 150 | - [VoltAgent](https://voltagent.dev/) 151 | - [Weights & Biases](https://wandb.ai/wandb_fc/product-announcements-fc/reports/Powering-Agent-Collaboration-Weights-Biases-Partners-with-Google-Cloud-on-Agent2Agent-Interoperability-Protocol---VmlldzoxMjE3NDg3OA) 152 | - [Wipro](https://www.wipro.com) 153 | - [Workday](https://www.workday.com) 154 | - [Writer](https://writer.com) 155 | - [Zenity](https://zenity.io) 156 | - [Zeotap](https://www.zeotap.com) 157 | - [Zocket Technologies , Inc.](https://zocket.ai) 158 | - [Zoom](https://www.zoom.us) 159 | - [zyprova](http://www.zyprova.com) 160 | -------------------------------------------------------------------------------- /docs/robots.txt: -------------------------------------------------------------------------------- 1 | # robots.txt for the A2A open-source project documentation site on Google GitHub Pages 2 | # This file guides web crawlers on which parts of the site to crawl and index. 3 | 4 | # Apply these rules to all web crawlers for maximum discoverability 5 | User-agent: * 6 | 7 | # Allow crawling of all public content by default. 8 | # We'll explicitly disallow specific paths below that aren't meant for public indexing. 9 | 10 | # Disallow common build, temporary, and configuration directories/files 11 | Disallow: /_site/ # Common Jekyll build directory 12 | Disallow: /_temp/ # General temporary directory 13 | Disallow: /build/ # General build output directory 14 | Disallow: /dist/ # Distribution/output directory 15 | Disallow: /.cache/ # Caching directory 16 | Disallow: /.git/ # Git repository files (if somehow exposed by accident) 17 | Disallow: /.github/ # GitHub Actions workflows and internal configuration files 18 | Disallow: /node_modules/ # Node.js dependencies (often large and irrelevant for indexing) 19 | Disallow: /vendor/ # Third-party libraries or assets 20 | 21 | # Disallow common configuration files that are not part of the public documentation 22 | Disallow: /_config.yml # Jekyll configuration file 23 | Disallow: /package.json # Node.js package configuration 24 | Disallow: /package-lock.json # Node.js package lock file 25 | Disallow: /yarn.lock # Yarn package lock file 26 | 27 | # Disallow specific file types that are often internal, temporary, or not meant for indexing 28 | Disallow: /*.bak$ # Backup files 29 | Disallow: /*.tmp$ # Temporary files 30 | Disallow: /*.log$ # Log files 31 | Disallow: /*.swp$ # Vim swap files 32 | 33 | # Disallow draft content if your static site generator supports it and these are not published 34 | Disallow: /_drafts/ 35 | 36 | # Specify the location of your XML sitemap. 37 | # This helps search engines discover all the pages on your site. 38 | Sitemap: https://google-a2a.github.io/A2A/sitemap.xml 39 | -------------------------------------------------------------------------------- /docs/sdk/python/index.md: -------------------------------------------------------------------------------- 1 | # Python SDK Reference 2 | 3 | This page contains SDK documentation for the [`a2a-sdk`](https://github.com/google-a2a/a2a-python) Python package. 4 | 5 | ```sh 6 | pip install a2a-sdk 7 | ``` 8 | 9 | ::: a2a 10 | options: 11 | show_root_heading: false 12 | show_source: false 13 | show_submodules: true 14 | members_order: alphabetical 15 | inherited_members: true 16 | 17 | 22 | -------------------------------------------------------------------------------- /docs/stylesheets/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2025 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* Index page styling */ 18 | 19 | .md-grid { 20 | max-width: 80%; 21 | } 22 | 23 | .footer { 24 | padding-bottom: 30vh; 25 | } 26 | 27 | .centered-logo-text-group { 28 | display: inline-flex; 29 | align-items: center; 30 | gap: 1.5em; 31 | margin-bottom: 0.5em; 32 | vertical-align: middle; 33 | } 34 | 35 | .centered-logo-text-group img { 36 | height: auto; 37 | } 38 | 39 | .centered-logo-text-group h1 { 40 | margin: 0; 41 | text-align: left; 42 | } 43 | 44 | .install-command-container { 45 | max-width: 600px; 46 | margin: 2.5em auto; 47 | padding: 1.5em 2em; 48 | background-color: var(--md-code-bg-color, #f5f5f5); 49 | border-radius: 8px; 50 | text-align: center; 51 | box-shadow: 0 3px 6px rgb(0 0 0 / 5%); 52 | border-left: 5px solid var(--md-primary-fg-color, #526cfe); 53 | margin-top: 30px; 54 | } 55 | 56 | .install-command-container p { 57 | font-size: 1.1em; 58 | color: var(--md-default-fg-color); 59 | margin-bottom: -10px; 60 | margin-top: -10px; 61 | } 62 | 63 | .install-command-container p code { 64 | font-size: 1.1em; 65 | font-weight: 600; 66 | padding: 0.3em 0.6em; 67 | background-color: var(--md-code-fg-color--light); 68 | border-radius: 4px; 69 | display: inline-block; 70 | line-height: 1.4; 71 | } 72 | -------------------------------------------------------------------------------- /docs/topics/a2a-and-mcp.md: -------------------------------------------------------------------------------- 1 | # A2A and MCP: Complementary Protocols for Agentic Systems 2 | 3 | ## A2A ❤️ MCP 4 | 5 | In the landscape of AI agent development, two key types of protocols are emerging to facilitate interoperability: those for connecting agents to **tools and resources**, and those for enabling **agent-to-agent collaboration**. The Agent2Agent (A2A) Protocol and the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) address these distinct but related needs. 6 | 7 | **TL;DR;** Agentic applications need both A2A and MCP. We recommend MCP for tools and A2A for agents. 8 | 9 | ## Why Different Protocols? 10 | 11 | The distinction arises from the nature of what an agent interacts with: 12 | 13 | - **Tools & Resources:** 14 | 15 | - These are typically primitives with well-defined, structured inputs and outputs. They perform specific, often stateless, functions (e.g., a calculator, a database query API, a weather lookup service). 16 | - Their behavior is generally predictable and transactional. 17 | - Interaction is often a single request-response cycle. 18 | 19 | - **Agents:** 20 | - These are more autonomous systems. They can reason, plan, use multiple tools, maintain state over longer interactions, and engage in complex, often multi-turn dialogues to achieve novel or evolving tasks. 21 | - Their behavior can be emergent and less predictable than a simple tool. 22 | - Interaction often involves ongoing tasks, context sharing, and negotiation. 23 | 24 | Agentic applications need to leverage both: agents use tools to gather information and perform actions, and agents collaborate with other agents to tackle broader, more complex goals. 25 | 26 | ## Model Context Protocol (MCP) 27 | 28 | - **Focus:** MCP standardizes how AI models and agents connect to and interact with **tools, APIs, data sources, and other external resources.** 29 | - **Mechanism:** It defines a structured way to describe tool capabilities (akin to function calling in Large Language Models), pass inputs to them, and receive structured outputs. 30 | - **Use Cases:** 31 | - Enabling an LLM to call an external API (e.g., fetch current stock prices). 32 | - Allowing an agent to query a database with specific parameters. 33 | - Connecting an agent to a set of predefined functions or services. 34 | - **Ecosystem:** MCP aims to create an ecosystem where tool providers can easily expose their services to various AI models and agent frameworks, and agent developers can easily consume these tools in a standardized way. 35 | 36 | ## Agent2Agent Protocol (A2A) 37 | 38 | - **Focus:** A2A standardizes how independent, often opaque, **AI agents communicate and collaborate with each other as peers.** 39 | - **Mechanism:** It provides an application-level protocol for agents to: 40 | - Discover each other's high-level skills and capabilities (via Agent Cards). 41 | - Negotiate interaction modalities (text, files, structured data). 42 | - Manage shared, stateful, and potentially long-running tasks. 43 | - Exchange conversational context, instructions, and complex, multi-part results. 44 | - **Use Cases:** 45 | - A customer service agent delegating a complex billing inquiry to a specialized billing agent, maintaining context of the customer interaction. 46 | - A travel planning agent coordinating with separate flight, hotel, and activity booking agents, managing a multi-stage booking process. 47 | - Agents exchanging information and status updates for a collaborative project that evolves over time. 48 | - **Key Difference from Tool Interaction:** A2A allows for more dynamic, stateful, and potentially multi-modal interactions than typically seen with simple tool calls. Agents using A2A communicate _as agents_ (or on behalf of users) rather than just invoking a discrete function. 49 | 50 | ## How A2A and MCP Complement Each Other 51 | 52 | A2A and MCP are not mutually exclusive; they are highly complementary and address different layers of an agentic system's interaction needs. 53 | 54 |
55 | 56 | ![Diagram showing A2A and MCP working together. A User interacts with Agent A via A2A. Agent A interacts with Agent B via A2A. Agent B uses MCP to interact with Tool 1 and Tool 2.](../assets/a2a-mcp.png){width="80%"} 57 | 58 | _An agentic application might use A2A to communicate with other agents, while each agent internally uses MCP to interact with its specific tools and resources._ 59 | 60 |
61 | 62 | ### Example Scenario: The Auto Repair Shop 63 | 64 | > Consider an auto repair shop staffed by autonomous AI agent "mechanics" who use special-purpose tools (such as vehicle jacks, multimeters, and socket wrenches) to diagnose and repair problems. The workers often have to diagnose and repair problems they have not seen before. The repair process can involve extensive conversations with a customer, research, and working with part suppliers. 65 | 66 | 1. **Customer Interaction (User-to-Agent via A2A):** 67 | 68 | - A customer (or their primary assistant agent) uses A2A to communicate with the "Shop Manager" agent: _"My car is making a rattling noise."_ 69 | - The Shop Manager agent uses A2A for a multi-turn diagnostic conversation: _"Can you send a video of the noise?"_, _"I see some fluid leaking. How long has this been happening?"_ 70 | 71 | 2. **Internal Tool Usage (Agent-to-Tool via MCP):** 72 | 73 | - The Mechanic agent, assigned the task by the Shop Manager, needs to diagnose the issue. It uses MCP to interact with its specialized tools: 74 | - MCP call to a "Vehicle Diagnostic Scanner" tool: `scan_vehicle_for_error_codes(vehicle_id='XYZ123')`. 75 | - MCP call to a "Repair Manual Database" tool: `get_repair_procedure(error_code='P0300', vehicle_make='Toyota', vehicle_model='Camry')`. 76 | - MCP call to a "Platform Lift" tool: `raise_platform(height_meters=2)`. 77 | 78 | 3. **Supplier Interaction (Agent-to-Agent via A2A):** 79 | - The Mechanic agent determines a specific part is needed. It uses A2A to communicate with a "Parts Supplier" agent: _"Do you have part #12345 in stock for a Toyota Camry 2018?"_ 80 | - The Parts Supplier agent, also an A2A-compliant system, responds, potentially leading to an order. 81 | 82 | In this example: 83 | 84 | - **A2A** facilitates the higher-level, conversational, and task-oriented interactions between the customer and the shop, and between the shop's agents and external supplier agents. 85 | - **MCP** enables the mechanic agent to use its specific, structured tools to perform its diagnostic and repair functions. 86 | 87 | ## Representing A2A Agents as MCP Resources 88 | 89 | It's conceivable that an A2A Server (a remote agent) could also expose some of its skills as MCP-compatible resources, especially if those skills are well-defined and can be invoked in a more tool-like, stateless manner. In such a case, another agent might "discover" this A2A agent's specific skill via an MCP-style tool description (perhaps derived from its Agent Card). 90 | 91 | However, the primary strength of A2A lies in its support for more flexible, stateful, and collaborative interactions that go beyond typical tool invocation. A2A is about agents _partnering_ on tasks, while MCP is more about agents _using_ capabilities. 92 | 93 | By leveraging both A2A for inter-agent collaboration and MCP for tool integration, developers can build more powerful, flexible, and interoperable AI systems. 94 | -------------------------------------------------------------------------------- /docs/topics/agent-discovery.md: -------------------------------------------------------------------------------- 1 | # Agent Discovery in A2A 2 | 3 | For AI agents to collaborate using the Agent2Agent (A2A) protocol, they first need to find each other and understand what capabilities the other agents offer. A2A standardizes the format of an agent's self-description through the **[Agent Card](../specification.md#5-agent-discovery-the-agent-card)**. However, the methods for discovering these Agent Cards can vary depending on the environment and requirements. 4 | 5 | ## The Role of the Agent Card 6 | 7 | The Agent Card is a JSON document that serves as a digital "business card" for an A2A Server (the remote agent). It is crucial for discovery and initiating interaction. Key information typically included in an Agent Card: 8 | 9 | - **Identity:** `name`, `description`, `provider` information. 10 | - **Service Endpoint:** The `url` where the A2A service can be reached. 11 | - **A2A Capabilities:** Supported protocol features like `streaming` or `pushNotifications`. 12 | - **Authentication:** Required authentication `schemes` (e.g., "Bearer", "OAuth2") to interact with the agent. 13 | - **Skills:** A list of specific tasks or functions the agent can perform (`AgentSkill` objects), including their `id`, `name`, `description`, `inputModes`, `outputModes`, and `examples`. 14 | 15 | Client agents parse the Agent Card to determine if a remote agent is suitable for a given task, how to structure requests for its skills, and how to communicate with it securely. 16 | 17 | ## Discovery Strategies 18 | 19 | Here are common strategies for how a client agent might discover the Agent Card of a remote agent: 20 | 21 | ### 1. Well-Known URI 22 | 23 | This is a recommended approach for public agents or agents intended for broad discoverability within a specific domain. 24 | 25 | - **Mechanism:** A2A Servers host their Agent Card at a standardized, "well-known" path on their domain. 26 | - **Standard Path:** `https://{agent-server-domain}/.well-known/agent.json` (following the principles of [RFC 8615](https://www.ietf.org/rfc/rfc8615.txt) for well-known URIs). 27 | - **Process:** 28 | 1. A client agent knows or programmatically discovers the domain of a potential A2A Server (e.g., `smart-thermostat.example.com`). 29 | 2. The client performs an HTTP `GET` request to `https://smart-thermostat.example.com/.well-known/agent.json`. 30 | 3. If the Agent Card exists and is accessible, the server returns it as a JSON response. 31 | - **Advantages:** Simple, standardized, and enables automated discovery by crawlers or systems that can resolve domains. Effectively reduces the discovery problem to "find the agent's domain." 32 | - **Considerations:** Best suited for agents intended for open discovery or discovery within an organization that controls the domain. The endpoint serving the Agent Card may itself require authentication if the card contains sensitive information. 33 | 34 | ### 2. Curated Registries (Catalog-Based Discovery) 35 | 36 | For enterprise environments, marketplaces, or specialized ecosystems, Agent Cards can be published to and discovered via a central registry or catalog. 37 | 38 | - **Mechanism:** An intermediary service (the registry) maintains a collection of Agent Cards. Clients query this registry to find agents based on various criteria (e.g., skills offered, tags, provider name, desired capabilities). 39 | - **Process:** 40 | 1. A2A Servers (or their administrators) register their Agent Cards with the registry service. The mechanism for this registration is outside the scope of the A2A protocol itself. 41 | 2. Client agents query the registry's API (e.g., "find agents with 'image-generation' skill that support streaming"). 42 | 3. The registry returns a list of matching Agent Cards or references to them. 43 | - **Advantages:** 44 | - Centralized management, curation, and governance of available agents. 45 | - Facilitates discovery based on functional capabilities rather than just domain names. 46 | - Can implement access controls, policies, and trust mechanisms at the registry level. 47 | - Enables scenarios like company-specific or team-specific agent catalogs, or public marketplaces of A2A-compliant agents. 48 | - **Considerations:** Requires an additional registry service. The A2A protocol does not currently define a standard API for such registries, though this is an area of potential future exploration and community standardization. 49 | 50 | ### 3. Direct Configuration / Private Discovery 51 | 52 | In many scenarios, especially within tightly coupled systems, for private agents, or during development and testing, clients might be directly configured with Agent Card information or a URL to fetch it. 53 | 54 | - **Mechanism:** The client application has hardcoded Agent Card details, reads them from a local configuration file, receives them through an environment variable, or fetches them from a private, proprietary API endpoint known to the client. 55 | - **Process:** This is highly specific to the application's deployment and configuration strategy. 56 | - **Advantages:** Simple and effective for known, static relationships between agents or when dynamic discovery is not a requirement. 57 | - **Considerations:** Less flexible for discovering new or updated agents dynamically. Changes to the remote agent's card might require re-configuration of the client. Proprietary API-based discovery is not standardized by A2A. 58 | 59 | ## Securing Agent Cards 60 | 61 | Agent Cards themselves can sometimes contain information that should be protected, such as: 62 | 63 | - The `url` of an internal-only or restricted-access agent. 64 | - Details in the `authentication.credentials` field if it's used for scheme-specific, non-secret information (e.g., an OAuth token URL). Storing actual plaintext secrets in an Agent Card is **strongly discouraged**. 65 | - Descriptions of sensitive or internal skills. 66 | 67 | **Protection Mechanisms:** 68 | 69 | - **Access Control on the Endpoint:** The HTTP endpoint serving the Agent Card (whether it's the `/.well-known/agent.json` path, a registry API, or a custom URL) should be secured using standard web practices if the card is not intended for public, unauthenticated access. 70 | - **mTLS:** Require mutual TLS for client authentication if appropriate for the trust model. 71 | - **Network Restrictions:** Limit access to specific IP ranges, VPCs, or private networks. 72 | - **Authentication:** Require standard HTTP authentication (e.g., OAuth 2.0 Bearer token, API Key) to access the Agent Card itself. 73 | - **Selective Disclosure by Registries:** Agent registries can implement logic to return different Agent Cards or varying levels of detail based on the authenticated client's identity and permissions. For example, a public query might return a limited card, while an authenticated partner query might receive a card with more details. 74 | 75 | It's crucial to remember that if an Agent Card were to contain sensitive data (again, **not recommended** for secrets), the card itself **must never** be available without strong authentication and authorization. The A2A protocol encourages authentication schemes where the client obtains dynamic credentials out-of-band, rather than relying on static secrets embedded in the Agent Card. 76 | 77 | ## Future Considerations 78 | 79 | The A2A community may explore standardizing aspects of registry interactions or more advanced, semantic discovery protocols in the future. Feedback and contributions in this area are welcome to enhance the discoverability and interoperability of A2A agents. 80 | -------------------------------------------------------------------------------- /docs/topics/enterprise-ready.md: -------------------------------------------------------------------------------- 1 | # Enterprise-Ready Features for A2A Agents 2 | 3 | The Agent2Agent (A2A) protocol is designed with enterprise requirements at its core. Instead of inventing new, proprietary standards for security and operations, A2A aims to integrate seamlessly with existing enterprise infrastructure and widely adopted best practices. A2A treats remote agents as standard, HTTP-based enterprise applications. This approach allows organizations to leverage their existing investments and expertise in security, monitoring, governance, and identity management. 4 | 5 | A key principle of A2A is that agents are typically "opaque" – they do not share internal memory, tools, or direct resource access with each other. This opacity naturally aligns with standard client/server security paradigms. 6 | 7 | ## 1. Transport Level Security (TLS) 8 | 9 | Ensuring the confidentiality and integrity of data in transit is fundamental. 10 | 11 | - **HTTPS Mandate:** All A2A communication in production environments **MUST** occur over HTTPS. 12 | - **Modern TLS Standards:** Implementations **SHOULD** use modern TLS versions (TLS 1.2 or higher is recommended) with strong, industry-standard cipher suites to protect data from eavesdropping and tampering. 13 | - **Server Identity Verification:** A2A Clients **SHOULD** verify the A2A Server's identity by validating its TLS certificate against trusted certificate authorities (CAs) during the TLS handshake. This prevents man-in-the-middle attacks. 14 | 15 | ## 2. Authentication 16 | 17 | A2A delegates authentication to standard web mechanisms, primarily relying on HTTP headers. Authentication requirements are advertised by the A2A Server in its [Agent Card](../specification.md#5-agent-discovery-the-agent-card). 18 | 19 | - **No In-Payload Identity:** A2A protocol payloads (JSON-RPC messages) do **not** carry user or client identity information. Identity is established at the transport/HTTP layer. 20 | - **Agent Card Declaration:** The A2A Server's `AgentCard` specifies the required authentication `schemes` (e.g., "Bearer", "OAuth2", "ApiKey", "Basic") in its `authentication` object. These scheme names often align with those defined in the [OpenAPI Specification for authentication](https://swagger.io/docs/specification/authentication/). 21 | - **Out-of-Band Credential Acquisition:** The A2A Client is responsible for obtaining the necessary credential materials (e.g., OAuth 2.0 tokens, API keys, JWTs) through processes external to the A2A protocol itself. This could involve OAuth flows (authorization code, client credentials), secure key distribution, etc. 22 | - **HTTP Header Transmission:** Credentials **MUST** be transmitted in standard HTTP headers as per the requirements of the chosen authentication scheme (e.g., `Authorization: Bearer `, `X-API-Key: `). 23 | - **Server-Side Validation:** The A2A Server **MUST** authenticate **every** incoming request based on the credentials provided in the HTTP headers and its declared requirements. 24 | - If authentication fails or is missing, the server **SHOULD** respond with standard HTTP status codes such as `401 Unauthorized` or `403 Forbidden`. 25 | - A `401 Unauthorized` response **SHOULD** include a `WWW-Authenticate` header indicating the required scheme(s), guiding the client on how to authenticate correctly. 26 | - **In-Task Authentication (Secondary Credentials):** If an agent, during a task, requires additional credentials for a _different_ system (e.g., to access a specific tool on behalf of the user), A2A recommends: 27 | 1. The A2A Server transitions the A2A task to the `input-required` state. 28 | 2. The `TaskStatus.message` (often using a `DataPart`) should provide details about the required authentication for the secondary system, potentially using an `AuthenticationInfo`-like structure. 29 | 3. The A2A Client then obtains these new credentials out-of-band for the secondary system. These credentials might be provided back to the A2A Server (if it's proxying the request) or used by the client to interact directly with the secondary system. 30 | 31 | ## 3. Authorization 32 | 33 | Once a client is authenticated, the A2A Server is responsible for authorizing the request. Authorization logic is specific to the agent's implementation, the data it handles, and applicable enterprise policies. 34 | 35 | - **Granular Control:** Authorization **SHOULD** be applied based on the authenticated identity (which could represent an end user, a client application, or both). 36 | - **Skill-Based Authorization:** Access can be controlled on a per-skill basis, as advertised in the Agent Card. For example, specific OAuth scopes might grant an authenticated client access to invoke certain skills but not others. 37 | - **Data and Action-Level Authorization:** Agents that interact with backend systems, databases, or tools **MUST** enforce appropriate authorization before performing sensitive actions or accessing sensitive data through those underlying resources. The agent acts as a gatekeeper. 38 | - **Principle of Least Privilege:** Grant only the necessary permissions required for a client or user to perform their intended operations via the A2A interface. 39 | 40 | ## 4. Data Privacy and Confidentiality 41 | 42 | - **Sensitivity Awareness:** Implementers must be acutely aware of the sensitivity of data exchanged in `Message` and `Artifact` parts of A2A interactions. 43 | - **Compliance:** Ensure compliance with relevant data privacy regulations (e.g., GDPR, CCPA, HIPAA, depending on the domain and data). 44 | - **Data Minimization:** Avoid including or requesting unnecessarily sensitive information in A2A exchanges. 45 | - **Secure Handling:** Protect data both in transit (via TLS, as mandated) and at rest (if persisted by agents) according to enterprise data security policies and regulatory requirements. 46 | 47 | ## 5. Tracing, Observability, and Monitoring 48 | 49 | A2A's reliance on HTTP allows for straightforward integration with standard enterprise tracing, logging, and monitoring tools. 50 | 51 | - **Distributed Tracing:** 52 | - A2A Clients and Servers **SHOULD** participate in distributed tracing systems (e.g., OpenTelemetry, Jaeger, Zipkin). 53 | - Trace context (trace IDs, span IDs) **SHOULD** be propagated via standard HTTP headers (e.g., W3C Trace Context headers like `traceparent` and `tracestate`). 54 | - This enables end-to-end visibility of requests as they flow across multiple agents and underlying services, which is invaluable for debugging and performance analysis. 55 | - **Comprehensive Logging:** Implement detailed logging on both client and server sides. Logs should include relevant identifiers such as `taskId`, `sessionId`, correlation IDs, and trace context to facilitate troubleshooting and auditing. 56 | - **Metrics:** A2A Servers should expose key operational metrics (e.g., request rates, error rates, task processing latency, resource utilization) to enable performance monitoring, alerting, and capacity planning. These can be integrated with systems like Prometheus or Google Cloud Monitoring. 57 | - **Auditing:** Maintain audit trails for significant events, such as task creation, critical state changes, and actions performed by agents, especially those involving sensitive data access, modifications, or high-impact operations. 58 | 59 | ## 6. API Management and Governance 60 | 61 | For A2A Servers exposed externally, across organizational boundaries, or even within large enterprises, integration with API Management solutions is highly recommended. This can provide: 62 | 63 | - **Centralized Policy Enforcement:** Consistent application of security policies (authentication, authorization), rate limiting, and quotas. 64 | - **Traffic Management:** Load balancing, routing, and mediation. 65 | - **Analytics and Reporting:** Insights into agent usage, performance, and trends. 66 | - **Developer Portals:** Facilitate discovery of A2A-enabled agents, provide documentation (including Agent Cards), and streamline onboarding for client developers. 67 | 68 | By adhering to these enterprise-grade practices, A2A implementations can be deployed securely, reliably, and manageably within complex organizational environments, fostering trust and enabling scalable inter-agent collaboration. 69 | -------------------------------------------------------------------------------- /docs/topics/key-concepts.md: -------------------------------------------------------------------------------- 1 | # Key Concepts in A2A 2 | 3 | The Agent2Agent (A2A) protocol is built around a set of core concepts that define how agents interact. Understanding these concepts is crucial for developing or integrating with A2A-compliant systems. 4 | 5 | ![A2A Actors showing a User, A2A Client (Client Agent), and A2A Server (Remote Agent)](../assets/a2a-actors.png){ width="70%" style="margin:20px auto;display:block;" } 6 | 7 | ## Core Actors 8 | 9 | - **User:** The end user (human or automated service) who initiates a request or goal that requires agent assistance. 10 | - **A2A Client (Client Agent):** An application, service, or another AI agent that acts on behalf of the user to request actions or information from a remote agent. The client initiates communication using the A2A protocol. 11 | - **A2A Server (Remote Agent):** An AI agent or agentic system that exposes an HTTP endpoint implementing the A2A protocol. It receives requests from clients, processes tasks, and returns results or status updates. The remote agent operates as an "opaque" system from the client's perspective, meaning the client doesn't need to know its internal workings, memory, or tools. 12 | 13 | ## Fundamental Communication Elements 14 | 15 | - **Agent Card:** 16 | 17 | - A JSON metadata document, typically discoverable at a well-known URL (e.g., `/.well-known/agent.json`), that describes an A2A Server. 18 | - It details the agent's identity (name, description), service endpoint URL, version, supported A2A capabilities (like streaming or push notifications), specific skills it offers, default input/output modalities, and authentication requirements. 19 | - Clients use the Agent Card to discover agents and understand how to interact with them securely and effectively. 20 | - See details in the [Protocol Specification: Agent Card](../specification.md#5-agent-discovery-the-agent-card). 21 | 22 | - **Task:** 23 | 24 | - When a client sends a message to an agent, the agent might determine that fulfilling the request requires a stateful task to be completed (e.g., "generate a report," "book a flight," "answer a question"). 25 | - Each task has a unique ID defined by the agent and progresses through a defined lifecycle (e.g., `submitted`, `working`, `input-required`, `completed`, `failed`). 26 | - Tasks are stateful and can involve multiple exchanges (messages) between the client and the server. 27 | - See details in the [Protocol Specification: Task Object](../specification.md#61-task-object). 28 | 29 | - **Message:** 30 | 31 | - Represents a single turn or unit of communication between a client and an agent. 32 | - Messages have a `role` (either `"user"` for client-sent messages or `"agent"` for server-sent messages) and contain one or more `Part` objects that carry the actual content. `messageId` part of the Message object is a unique identifier for each message set by the sender of the message. 33 | - Used for conveying instructions, context, questions, answers, or status updates that are not necessarily formal `Artifacts`. 34 | - See details in the [Protocol Specification: Message Object](../specification.md#64-message-object). 35 | 36 | - **Part:** 37 | 38 | - The fundamental unit of content within a `Message` or an `Artifact`. Each part has a specific `type` and can carry different kinds of data: 39 | - `TextPart`: Contains plain textual content. 40 | - `FilePart`: Represents a file, which can be transmitted as inline base64-encoded bytes or referenced via a URI. Includes metadata like filename and Media Type. 41 | - `DataPart`: Carries structured JSON data, useful for forms, parameters, or any machine-readable information. 42 | - See details in the [Protocol Specification: Part Union Type](../specification.md#65-part-union-type). 43 | 44 | - **Artifact:** 45 | - Represents a tangible output or result generated by the remote agent during the processing of a task. 46 | - Examples include generated documents, images, spreadsheets, structured data results, or any other self-contained piece of information that is a direct result of the task. 47 | - Artifacts are composed of one or more `Part` objects and can be streamed incrementally. 48 | - See details in the [Protocol Specification: Artifact Object](../specification.md#67-artifact-object). 49 | 50 | ## Interaction Mechanisms 51 | 52 | - **Request/Response (Polling):** 53 | 54 | - The client sends a request (e.g., using the `message/send` RPC method) and receives a response from the server. 55 | - If the interaction requires a stateful long-running task, the server might initially respond with a `working` status. The client would then periodically call `tasks/get` to poll for updates until the task reaches a terminal state (e.g., `completed`, `failed`). 56 | 57 | - **Streaming (Server-Sent Events - SSE):** 58 | 59 | - For tasks that produce results incrementally or provide real-time progress updates. 60 | - The client initiates an interaction with the server using `message/stream`. 61 | - The server responds with an HTTP connection that remains open, over which it sends a stream of Server-Sent Events (SSE). 62 | - These events can be `Task`, `Message`, or ``TaskStatusUpdateEvent` (for status changes) or `TaskArtifactUpdateEvent` (for new or updated artifact chunks). 63 | - This requires the server to advertise the `streaming` capability in its Agent Card. 64 | - Learn more about [Streaming & Asynchronous Operations](./streaming-and-async.md). 65 | 66 | - **Push Notifications:** 67 | - For very long-running tasks or scenarios where maintaining a persistent connection (like SSE) is impractical. 68 | - The client can provide a webhook URL when initiating a task (or by calling `tasks/pushNotificationConfig/set`). 69 | - When the task status changes significantly (e.g., completes, fails, or requires input), the server can send an asynchronous notification (an HTTP POST request) to this client-provided webhook. 70 | - This requires the server to advertise the `pushNotifications` capability in its Agent Card. 71 | - Learn more about [Streaming & Asynchronous Operations](./streaming-and-async.md). 72 | 73 | ## Other Important Concepts 74 | 75 | - **Context (`contextId`):** A server-generated identifier that can be used to logically group multiple related `Task` objects, providing context across a series of interactions. 76 | - **Transport and Format:** A2A communication occurs over HTTP(S). JSON-RPC 2.0 is used as the payload format for all requests and responses. 77 | - **Authentication & Authorization:** A2A relies on standard web security practices. Authentication requirements are declared in the Agent Card, and credentials (e.g., OAuth tokens, API keys) are typically passed via HTTP headers, separate from the A2A protocol messages themselves. 78 | - Learn more about [Enterprise-Ready Features](./enterprise-ready.md). 79 | - **Agent Discovery:** The process by which clients find Agent Cards to learn about available A2A Servers and their capabilities. 80 | - Learn more about [Agent Discovery](./agent-discovery.md). 81 | 82 | By understanding these core components and mechanisms, developers can effectively design, implement, and utilize A2A for building interoperable and collaborative AI agent systems. 83 | -------------------------------------------------------------------------------- /docs/topics/streaming-and-async.md: -------------------------------------------------------------------------------- 1 | # Streaming & Asynchronous Operations in A2A 2 | 3 | The Agent2Agent (A2A) protocol is designed to handle tasks that may not complete immediately. Many AI-driven operations can be long-running, involve multiple steps, produce incremental results, or require human intervention. A2A provides robust mechanisms for managing such asynchronous interactions, ensuring that clients can receive updates effectively, whether they remain continuously connected or operate in a more disconnected fashion. 4 | 5 | ## 1. Streaming with Server-Sent Events (SSE) 6 | 7 | For tasks that produce incremental results (like generating a long document or streaming media) or provide ongoing status updates, A2A supports real-time communication using Server-Sent Events (SSE). This is ideal when the client can maintain an active HTTP connection with the A2A Server. 8 | 9 | **Key Characteristics:** 10 | 11 | - **Initiation:** The client uses the `message/stream` RPC method to send an initial message (e.g., a prompt or command) and simultaneously subscribe to updates for that task. 12 | - **Server Capability:** The A2A Server must indicate its support for streaming by setting `capabilities.streaming: true` in its [Agent Card](../specification.md#552-agentcapabilities-object). 13 | - **Server Response (Connection):** If the subscription is successful, the server responds with an HTTP `200 OK` status and a `Content-Type: text/event-stream`. This HTTP connection remains open for the server to push events. 14 | - **Event Structure:** The server sends events over this stream. Each event's `data` field contains a JSON-RPC 2.0 Response object, specifically a [`SendStreamingMessageResponse`](../specification.md#721-sendstreamingmessageresponse-object). The `id` in this JSON-RPC response matches the `id` from the client's original `message/stream` request. 15 | - **Event Types (within `SendStreamingMessageResponse.result`):** 16 | - [`Task`](../specification.md#61-task-object): Represents the stateful unit of work being processed by the A2A Server for an A2A Client. 17 | - [`TaskStatusUpdateEvent`](../specification.md#722-taskstatusupdateevent-object): Communicates changes in the task's lifecycle state (e.g., from `working` to `input-required` or `completed`). It can also provide intermediate messages from the agent (e.g., "I'm currently analyzing the data..."). 18 | - [`TaskArtifactUpdateEvent`](../specification.md#723-taskartifactupdateevent-object): Delivers new or updated [Artifacts](../specification.md#67-artifact-object) generated by the task. This is used to stream large files or data structures in chunks. This object itself contains fields like `append`, and `lastChunk` to help the client reassemble the complete artifact. 19 | - **Stream Termination:** The server signals the end of updates for a particular interaction cycle (i.e., for the current `message/stream` request) by setting `final: true` in a `TaskStatusUpdateEvent`. This typically occurs when the task reaches a terminal state (`completed`, `failed`, `canceled`) or an `input-required` state (where the server expects further input from the client). After sending a `final: true` event, the server usually closes the SSE connection for that specific request. 20 | - **Resubscription:** If a client's SSE connection breaks prematurely while a task is still active (and the server hasn't sent a `final: true` event for that phase), the client can attempt to reconnect to the stream using the `tasks/resubscribe` RPC method. The server's behavior regarding missed events during the disconnection period (e.g., whether it backfills or only sends new updates) is implementation-dependent. 21 | 22 | **When to Use Streaming:** 23 | 24 | - Real-time progress monitoring of long-running tasks. 25 | - Receiving large results (artifacts) incrementally, allowing processing to begin before the entire result is available. 26 | - Interactive, conversational exchanges where immediate feedback or partial responses are beneficial. 27 | - Applications requiring low-latency updates from the agent. 28 | 29 | Refer to the Protocol Specification for detailed structures: 30 | 31 | - [`message/stream`](../specification.md#72-messagestream) 32 | - [`tasks/resubscribe`](../specification.md#77-tasksresubscribe) 33 | 34 | ## 2. Push Notifications for Disconnected Scenarios 35 | 36 | For very long-running tasks (e.g., lasting minutes, hours, or even days) or when clients cannot or prefer not to maintain persistent connections (like mobile clients or serverless functions), A2A supports asynchronous updates via push notifications. This mechanism allows the A2A Server to actively notify a client-provided webhook when a significant task update occurs. 37 | 38 | **Key Characteristics:** 39 | 40 | - **Server Capability:** The A2A Server must indicate its support for this feature by setting `capabilities.pushNotifications: true` in its [Agent Card](../specification.md#552-agentcapabilities-object). 41 | - **Configuration:** The client provides a [`PushNotificationConfig`](../specification.md#68-pushnotificationconfig-object) to the server. 42 | - This configuration can be supplied: 43 | - Within the initial `message/send` or `message/stream` request (via the optional `pushNotification` parameter in `TaskSendParams`). 44 | - Separately, using the `tasks/pushNotificationConfig/set` RPC method for an existing task. 45 | 46 | - The `PushNotificationConfig` includes: 47 | - `url`: The absolute HTTPS webhook URL where the A2A Server should send (POST) task update notifications. 48 | - `token` (optional): A client-generated opaque string (e.g., a secret or task-specific identifier). The server SHOULD include this token in the notification request (e.g., in a custom header like `X-A2A-Notification-Token`) for validation by the client's webhook receiver. 49 | - `authentication` (optional): An [`AuthenticationInfo`](../specification.md#69-pushnotificationauthenticationinfo-object) object specifying how the A2A Server should authenticate itself _to the client's webhook URL_. The client (receiver of the webhook) defines these authentication requirements. 50 | 51 | - **Notification Trigger:** The A2A Server decides when to send a push notification. Typically, this happens when a task reaches a significant state change, such as transitioning to a terminal state (`completed`, `failed`, `canceled`, `rejected`) or an `input-required` or `auth-required` state, particularly after its associated message and artifacts are fully generated and stable. 52 | - **Notification Payload:** The A2A protocol itself does **not** strictly define the HTTP body payload of the push notification sent by the server to the client's webhook. However, the notification **SHOULD** contain sufficient information for the client to identify the `Task ID` and understand the general nature of the update (e.g., the new `TaskState`). Servers might send a minimal payload (just `Task ID` and new state) or a more comprehensive one (e.g., a summary or even the full [`Task`](../specification.md#61-task-object) object). 53 | - **Client Action:** Upon receiving a push notification (and successfully verifying its authenticity and relevance), the client typically uses the `tasks/get` RPC method with the `task ID` from the notification to retrieve the complete, updated `Task` object, including any new artifacts or detailed messages. 54 | 55 | **The Push Notification Service (Client-Side Webhook Infrastructure):** 56 | 57 | - The target `url` specified in `PushNotificationConfig.url` points to a **Push Notification Service**. This service is a component on the client's side (or a service the client subscribes to) responsible for receiving the HTTP POST notification from the A2A Server. 58 | - Its responsibilities include: 59 | - Authenticating the incoming notification (i.e., verifying it's from the legitimate A2A Server). 60 | - Validating the notification's relevance (e.g., checking the `token`). 61 | - Relaying the notification or its content to the appropriate client application logic or system. 62 | - In simple scenarios (e.g., local development), the client application itself might directly expose the webhook endpoint. 63 | - In enterprise or production settings, this is often a robust, secure service that handles incoming webhooks, authenticates callers, and routes messages (e.g., to a message queue, an internal API, a mobile push notification gateway, or another event-driven system). 64 | 65 | ### Security Considerations for Push Notifications 66 | 67 | Security is paramount for push notifications due to their asynchronous and server-initiated outbound nature. Both the A2A Server (sending the notification) and the client's webhook receiver have responsibilities. 68 | 69 | #### A2A Server Security (When Sending Notifications to Client Webhook) 70 | 71 | 1. **Webhook URL Validation:** 72 | 73 | - Servers **SHOULD NOT** blindly trust and send POST requests to any `url` provided by a client in `PushNotificationConfig`. Malicious clients could provide URLs pointing to internal services or unrelated third-party systems to cause harm (Server-Side Request Forgery - SSRF attacks) or act as Distributed Denial of Service (DDoS) amplifiers. 74 | - **Mitigation Strategies:** 75 | - **Allowlisting:** Maintain an allowlist of trusted domains or IP ranges for webhook URLs, if feasible. 76 | - **Ownership Verification / Challenge-Response:** Before sending actual notifications, the server can (and SHOULD ideally) perform a verification step. For example, it could issue an HTTP `GET` or `OPTIONS` request to the proposed webhook URL with a unique `validationToken` (as a query parameter or header). The webhook service must respond appropriately (e.g., echo back the token or confirm readiness) to prove ownership and reachability. The [A2A Python samples](https://github.com/google-a2a/A2A/blob/main/samples/python/agents/langgraph/task_manager.py) demonstrate a simple validation token check mechanism. 77 | - **Network Controls:** Use egress firewalls or network policies to restrict where the A2A Server can send outbound HTTP requests. 78 | 79 | 2. **Authenticating to the Client's Webhook:** 80 | - The A2A Server **MUST** authenticate itself to the client's webhook URL according to the scheme(s) specified in `PushNotificationConfig.authentication`. 81 | - Common authentication schemes for server-to-server webhooks include: 82 | - **Bearer Tokens (OAuth 2.0):** The A2A Server obtains an access token (e.g., using the OAuth 2.0 client credentials grant flow if the webhook provider supports it) for an audience/scope representing the client's webhook, and includes it in the `Authorization: Bearer ` header of the notification POST request. 83 | - **API Keys:** A pre-shared API key that the A2A Server includes in a specific HTTP header (e.g., `X-Api-Key`). 84 | - **HMAC Signatures:** The A2A Server signs the request payload (or parts of the request) with a shared secret key using HMAC, and includes the signature in a header (e.g., `X-Hub-Signature`). The webhook receiver then verifies this signature. 85 | - **Mutual TLS (mTLS):** If supported by the client's webhook infrastructure, the A2A Server can present a client TLS certificate. 86 | 87 | #### Client Webhook Receiver Security (When Receiving Notifications from A2A Server) 88 | 89 | 1. **Authenticating the A2A Server:** 90 | 91 | - The webhook endpoint **MUST** rigorously verify the authenticity of incoming notification requests to ensure they originate from the legitimate A2A Server and not an imposter. 92 | - **Verify Signatures/Tokens:** 93 | - If using JWTs (e.g., as Bearer tokens), validate the JWT's signature against the A2A Server's trusted public keys (e.g., fetched from a JWKS endpoint provided by the A2A Server, if applicable). Also, validate claims like `iss` (issuer), `aud` (audience - should identify your webhook), `iat` (issued at), and `exp` (expiration time). 94 | - If using HMAC signatures, recalculate the signature on the received payload using the shared secret and compare it to the signature in the request header. 95 | - If using API keys, ensure the key is valid and known. 96 | - **Validate `PushNotificationConfig.token`:** If the client provided an opaque `token` in its `PushNotificationConfig` when setting up notifications for the task, the webhook should check that the incoming notification includes this exact token (e.g., in a custom header like `X-A2A-Notification-Token`). This helps ensure the notification is intended for this specific client context and task, adding a layer of authorization. 97 | 98 | 2. **Preventing Replay Attacks:** 99 | 100 | - **Timestamps:** Notifications should ideally include a timestamp (e.g., `iat` - issued at - claim in a JWT, or a custom timestamp header). The webhook should reject notifications that are too old (e.g., older than a few minutes) to prevent attackers from replaying old, captured notifications. The timestamp should be part of the signed payload (if using signatures) to ensure its integrity. 101 | - **Nonces/Unique IDs:** For critical notifications, consider using unique, single-use identifiers (nonces or event IDs) for each notification. The webhook should track received IDs (for a reasonable window) to prevent processing duplicate notifications. A JWT's `jti` (JWT ID) claim can serve this purpose. 102 | 103 | 3. **Secure Key Management and Rotation:** 104 | - If using cryptographic keys (symmetric secrets for HMAC, or asymmetric key pairs for JWT signing/mTLS), implement secure key management practices, including regular key rotation. 105 | - For asymmetric keys where the A2A Server signs and the client webhook verifies, protocols like JWKS (JSON Web Key Set) allow the server to publish its public keys (including new ones during rotation) at a well-known endpoint. Client webhooks can then dynamically fetch the correct public key for signature verification, facilitating smoother key rotation. 106 | 107 | ##### Example Asymmetric Key Flow (JWT + JWKS) 108 | 109 | 1. Client sets `PushNotificationConfig` specifying `authentication.schemes: ["Bearer"]` and possibly an expected `issuer` or `audience` for the JWT. 110 | 2. A2A Server, when sending a notification: 111 | - Generates a JWT, signing it with its private key. The JWT includes claims like `iss` (issuer), `aud` (audience - the webhook), `iat` (issued at), `exp` (expires), `jti` (JWT ID), and `taskId`. 112 | - The JWT header (`alg` and `kid`) indicates the signing algorithm and key ID. 113 | - The A2A Server makes its public keys available via a JWKS endpoint (URL for this endpoint might be known to the webhook provider or discovered). 114 | 3. Client Webhook, upon receiving the notification: 115 | - Extracts the JWT from the `Authorization` header. 116 | - Inspects the `kid` in the JWT header. 117 | - Fetches the corresponding public key from the A2A Server's JWKS endpoint (caching keys is recommended). 118 | - Verifies the JWT signature using the public key. 119 | - Validates claims (`iss`, `aud`, `iat`, `exp`, `jti`). 120 | - Checks the `PushNotificationConfig.token` if provided. 121 | 122 | This comprehensive, layered approach to security for push notifications ensures that messages are authentic, integral, and timely, protecting both the sending A2A Server and the receiving client webhook infrastructure. 123 | -------------------------------------------------------------------------------- /docs/topics/what-is-a2a.md: -------------------------------------------------------------------------------- 1 | # What is A2A? 2 | 3 | The Agent2Agent (A2A) Protocol is an open standard designed to solve a fundamental challenge in the rapidly evolving landscape of artificial intelligence: **how do AI agents, built by different teams, using different technologies, and owned by different organizations, communicate and collaborate effectively?** 4 | 5 | As AI agents become more specialized and capable, the need for them to work together on complex tasks increases. Imagine a user asking their primary AI assistant to plan an international trip. This single request might involve coordinating the capabilities of several specialized agents: 6 | 7 | 1. An agent for flight bookings. 8 | 2. Another agent for hotel reservations. 9 | 3. A third for local tour recommendations and bookings. 10 | 4. A fourth to handle currency conversion and travel advisories. 11 | 12 | Without a common communication protocol, integrating these diverse agents into a cohesive user experience is a significant engineering hurdle. Each integration would likely be a custom, point-to-point solution, making the system difficult to scale, maintain, and extend. 13 | 14 | ## The A2A Solution 15 | 16 | A2A provides a standardized way for these independent, often "opaque" (black-box) agentic systems to interact. It defines: 17 | 18 | - **A common transport and format:** JSON-RPC 2.0 over HTTP(S) for how messages are structured and transmitted. 19 | - **Discovery mechanisms (Agent Cards):** How agents can advertise their capabilities and be found by other agents. 20 | - **Task management workflows:** How collaborative tasks are initiated, progressed, and completed. This includes support for tasks that may be long-running or require multiple turns of interaction. 21 | - **Support for various data modalities:** How agents exchange not just text, but also files, structured data (like forms), and potentially other rich media. 22 | - **Core principles for security and asynchronicity:** Guidelines for secure communication and handling tasks that might take significant time or involve human-in-the-loop processes. 23 | 24 | ## Key Design Principles of A2A 25 | 26 | The development of A2A is guided by several core principles: 27 | 28 | - **Simplicity:** Leverage existing, well-understood standards like HTTP, JSON-RPC, and Server-Sent Events (SSE) where possible, rather than reinventing the wheel. 29 | - **Enterprise Readiness:** Address critical enterprise needs such as authentication, authorization, security, privacy, tracing, and monitoring from the outset by aligning with standard web practices. 30 | - **Asynchronous First:** Natively support long-running tasks and scenarios where agents or users might not be continuously connected, through mechanisms like streaming and push notifications. 31 | - **Modality Agnostic:** Allow agents to communicate using a variety of content types, enabling rich and flexible interactions beyond plain text. 32 | - **Opaque Execution:** Enable collaboration without requiring agents to expose their internal logic, memory, or proprietary tools. Agents interact based on declared capabilities and exchanged context, preserving intellectual property and enhancing security. 33 | 34 | ## Benefits of Using A2A 35 | 36 | Adopting A2A can lead to significant advantages: 37 | 38 | - **Increased Interoperability:** Break down silos between different AI agent ecosystems, allowing agents from various vendors and frameworks to work together. 39 | - **Enhanced Agent Capabilities:** Allow developers to create more sophisticated applications by composing the strengths of multiple specialized agents. 40 | - **Reduced Integration Complexity:** Standardize the "how" of agent communication, allowing teams to focus on the "what" – the value their agents provide. 41 | - **Fostering Innovation:** Encourage the development of a richer ecosystem of specialized agents that can readily plug into larger collaborative workflows. 42 | - **Future-Proofing:** Provide a flexible framework that can adapt as agent technologies continue to evolve. 43 | 44 | By establishing common ground for agent-to-agent communication, A2A aims to accelerate the adoption and utility of AI agents across diverse industries and applications, paving the way for more powerful and collaborative AI systems. 45 | 46 | [Watch the A2A Demo Video](https://storage.googleapis.com/gweb-developer-goog-blog-assets/original_videos/A2A_demo_v4.mp4) 47 | 48 | Next, learn about the [Key Concepts](./key-concepts.md) that form the foundation of the A2A protocol. 49 | -------------------------------------------------------------------------------- /docs/tutorials/python/1-introduction.md: -------------------------------------------------------------------------------- 1 | # Python Quickstart Tutorial: Building an A2A Agent 2 | 3 | Welcome to the Agent2Agent (A2A) Python Quickstart Tutorial! 4 | 5 | In this tutorial, you will explore a simple "echo" A2A server using the Python SDK. This will introduce you to the fundamental concepts and components of an A2A server. You will then look at a more advanced example that integrates a Large Language Model (LLM). 6 | 7 | This hands-on guide will help you understand: 8 | 9 | - The basic concepts behind the A2A protocol. 10 | - How to set up a Python environment for A2A development using the SDK. 11 | - How Agent Skills and Agent Cards describe an agent. 12 | - How an A2A server handles tasks. 13 | - How to interact with an A2A server using a client. 14 | - How streaming capabilities and multi-turn interactions work. 15 | - How an LLM can be integrated into an A2A agent. 16 | 17 | By the end of this tutorial, you will have a functional understanding of A2A agents and a solid foundation for building or integrating A2A-compliant applications. 18 | 19 | ## Tutorial Sections 20 | 21 | The tutorial is broken down into the following steps: 22 | 23 | 1. **[Introduction (This Page)](./1-introduction.md)** 24 | 2. **[Setup](./2-setup.md)**: Prepare your Python environment and the A2A SDK. 25 | 3. **[Agent Skills & Agent Card](./3-agent-skills-and-card.md)**: Define what your agent can do and how it describes itself. 26 | 4. **[The Agent Executor](./4-agent-executor.md)**: Understand how the agent logic is implemented. 27 | 5. **[Starting the Server](./5-start-server.md)**: Run the Helloworld A2A server. 28 | 6. **[Interacting with the Server](./6-interact-with-server.md)**: Send requests to your agent. 29 | 7. **[Streaming & Multi-Turn Interactions](./7-streaming-and-multiturn.md)**: Explore advanced capabilities with the LangGraph example. 30 | 8. **[Next Steps](./8-next-steps.md)**: Explore further possibilities with A2A. 31 | 32 | Let's get started! 33 | -------------------------------------------------------------------------------- /docs/tutorials/python/2-setup.md: -------------------------------------------------------------------------------- 1 | # 2. Setup Your Environment 2 | 3 | ## Prerequisites 4 | 5 | - Python 3.13 or higher. 6 | - Access to a terminal or command prompt. 7 | - Git, for cloning the repository. 8 | - A code editor (e.g., Visual Studio Code) is recommended. 9 | 10 | ## Clone the Repository 11 | 12 | If you haven't already, clone the A2A Samples repository: 13 | 14 | ```bash 15 | git clone https://github.com/google-a2a/a2a-samples.git -b main --depth 1 16 | cd a2a-samples 17 | ``` 18 | 19 | ## Python Environment & SDK Installation 20 | 21 | We recommend using a virtual environment for Python projects. The A2A Python SDK uses `uv` for dependency management, but you can use `pip` with `venv` as well. 22 | 23 | 1. **Create and activate a virtual environment:** 24 | 25 | Using `venv` (standard library): 26 | 27 | === "Mac/Linux" 28 | 29 | ```sh 30 | python -m venv .venv 31 | source .venv/bin/activate 32 | ``` 33 | 34 | === "Windows" 35 | 36 | ```powershell 37 | python -m venv .venv 38 | .venv\Scripts\activate 39 | ``` 40 | 41 | 2. **Install needed Python dependencies along with the A2A SDK and its dependencies:** 42 | 43 | ```bash 44 | pip install -r samples/python/requirements.txt 45 | ``` 46 | 47 | ## Verify Installation 48 | 49 | After installation, you should be able to import the `a2a` package in a Python interpreter: 50 | 51 | ```bash 52 | python -c "import a2a; print('A2A SDK imported successfully')" 53 | ``` 54 | 55 | If this command runs without error and prints the success message, your environment is set up correctly. 56 | -------------------------------------------------------------------------------- /docs/tutorials/python/3-agent-skills-and-card.md: -------------------------------------------------------------------------------- 1 | # 3. Agent Skills & Agent Card 2 | 3 | Before an A2A agent can do anything, it needs to define what it _can_ do (its skills) and how other agents or clients can find out about these capabilities (its Agent Card). 4 | 5 | We'll use the `helloworld` example located in [`a2a-samples/samples/python/agents/helloworld/`](https://github.com/google-a2a/a2a-samples/tree/main/samples/python/agents/helloworld). 6 | 7 | ## Agent Skills 8 | 9 | An **Agent Skill** describes a specific capability or function the agent can perform. It's a building block that tells clients what kinds of tasks the agent is good for. 10 | 11 | Key attributes of an `AgentSkill` (defined in `a2a.types`): 12 | 13 | - `id`: A unique identifier for the skill. 14 | - `name`: A human-readable name. 15 | - `description`: A more detailed explanation of what the skill does. 16 | - `tags`: Keywords for categorization and discovery. 17 | - `examples`: Sample prompts or use cases. 18 | - `inputModes` / `outputModes`: Supported Media Types for input and output (e.g., "text/plain", "application/json"). 19 | 20 | In `__main__.py`, you can see how a skill for the Helloworld agent is defined: 21 | 22 | ```python { .no-copy } 23 | --8<-- "https://raw.githubusercontent.com/google-a2a/a2a-samples/refs/heads/main/samples/python/agents/helloworld/__main__.py:AgentSkill" 24 | ``` 25 | 26 | This skill is very simple: it's named "Returns hello world" and primarily deals with text. 27 | 28 | ## Agent Card 29 | 30 | The **Agent Card** is a JSON document that an A2A Server makes available, typically at a `.well-known/agent.json` endpoint. It's like a digital business card for the agent. 31 | 32 | Key attributes of an `AgentCard` (defined in `a2a.types`): 33 | 34 | - `name`, `description`, `version`: Basic identity information. 35 | - `url`: The endpoint where the A2A service can be reached. 36 | - `capabilities`: Specifies supported A2A features like `streaming` or `pushNotifications`. 37 | - `defaultInputModes` / `defaultOutputModes`: Default Media Types for the agent. 38 | - `skills`: A list of `AgentSkill` objects that the agent offers. 39 | 40 | The `helloworld` example defines its Agent Card like this: 41 | 42 | ```python { .no-copy } 43 | --8<-- "https://raw.githubusercontent.com/google-a2a/a2a-samples/refs/heads/main/samples/python/agents/helloworld/__main__.py:AgentCard" 44 | ``` 45 | 46 | This card tells us the agent is named "Hello World Agent", runs at `http://localhost:9999/`, supports text interactions, and has the `hello_world` skill. It also indicates public authentication, meaning no specific credentials are required. 47 | 48 | Understanding the Agent Card is crucial because it's how a client discovers an agent and learns how to interact with it. 49 | -------------------------------------------------------------------------------- /docs/tutorials/python/4-agent-executor.md: -------------------------------------------------------------------------------- 1 | # 4. The Agent Executor 2 | 3 | The core logic of how an A2A agent processes requests and generates responses/events is handled by an **Agent Executor**. The A2A Python SDK provides an abstract base class `a2a.server.agent_execution.AgentExecutor` that you implement. 4 | 5 | ## `AgentExecutor` Interface 6 | 7 | The `AgentExecutor` class defines two primary methods: 8 | 9 | - `async def execute(self, context: RequestContext, event_queue: EventQueue)`: Handles incoming requests that expect a response or a stream of events. It processes the user's input (available via `context`) and uses the `event_queue` to send back `Message`, `Task`, `TaskStatusUpdateEvent`, or `TaskArtifactUpdateEvent` objects. 10 | - `async def cancel(self, context: RequestContext, event_queue: EventQueue)`: Handles requests to cancel an ongoing task. 11 | 12 | The `RequestContext` provides information about the incoming request, such as the user's message and any existing task details. The `EventQueue` is used by the executor to send events back to the client. 13 | 14 | ## Helloworld Agent Executor 15 | 16 | Let's look at `agent_executor.py`. It defines `HelloWorldAgentExecutor`. 17 | 18 | 1. **The Agent (`HelloWorldAgent`)**: 19 | This is a simple helper class that encapsulates the actual "business logic". 20 | 21 | ```python { .no-copy } 22 | --8<-- "https://raw.githubusercontent.com/google-a2a/a2a-samples/refs/heads/main/samples/python/agents/helloworld/agent_executor.py:HelloWorldAgent" 23 | ``` 24 | 25 | It has a simple `invoke` method that returns the string "Hello World". 26 | 27 | 2. **The Executor (`HelloWorldAgentExecutor`)**: 28 | This class implements the `AgentExecutor` interface. 29 | 30 | - **`__init__`**: 31 | 32 | ```python { .no-copy } 33 | --8<-- "https://raw.githubusercontent.com/google-a2a/a2a-samples/refs/heads/main/samples/python/agents/helloworld/agent_executor.py:HelloWorldAgentExecutor_init" 34 | ``` 35 | 36 | It instantiates the `HelloWorldAgent`. 37 | 38 | - **`execute`**: 39 | 40 | ```python { .no-copy } 41 | --8<-- "https://raw.githubusercontent.com/google-a2a/a2a-samples/refs/heads/main/samples/python/agents/helloworld/agent_executor.py:HelloWorldAgentExecutor_execute" 42 | ``` 43 | 44 | When a `message/send` or `message/stream` request comes in (both are handled by `execute` in this simplified executor): 45 | 46 | 1. It calls `self.agent.invoke()` to get the "Hello World" string. 47 | 2. It creates an A2A `Message` object using the `new_agent_text_message` utility function. 48 | 3. It enqueues this message onto the `event_queue`. The underlying `DefaultRequestHandler` will then process this queue to send the response(s) to the client. For a single message like this, it will result in a single response for `message/send` or a single event for `message/stream` before the stream closes. 49 | 50 | - **`cancel`**: 51 | The Helloworld example's `cancel` method simply raises an exception, indicating that cancellation is not supported for this basic agent. 52 | 53 | ```python { .no-copy } 54 | --8<-- "https://raw.githubusercontent.com/google-a2a/a2a-samples/refs/heads/main/samples/python/agents/helloworld/agent_executor.py:HelloWorldAgentExecutor_cancel" 55 | ``` 56 | 57 | The `AgentExecutor` acts as the bridge between the A2A protocol (managed by the request handler and server application) and your agent's specific logic. It receives context about the request and uses an event queue to communicate results or updates back. 58 | -------------------------------------------------------------------------------- /docs/tutorials/python/5-start-server.md: -------------------------------------------------------------------------------- 1 | # 5. Starting the Server 2 | 3 | Now that we have an Agent Card and an Agent Executor, we can set up and start the A2A server. 4 | 5 | The A2A Python SDK provides an `A2AStarletteApplication` class that simplifies running an A2A-compliant HTTP server. It uses [Starlette](https://www.starlette.io/) for the web framework and is typically run with an ASGI server like [Uvicorn](https://www.uvicorn.org/). 6 | 7 | ## Server Setup in Helloworld 8 | 9 | Let's look at `__main__.py` again to see how the server is initialized and started. 10 | 11 | ```python { .no-copy } 12 | --8<-- "https://raw.githubusercontent.com/google-a2a/a2a-samples/refs/heads/main/samples/python/agents/helloworld/__main__.py" 13 | ``` 14 | 15 | Let's break this down: 16 | 17 | 1. **`DefaultRequestHandler`**: 18 | 19 | - The SDK provides `DefaultRequestHandler`. This handler takes your `AgentExecutor` implementation (here, `HelloWorldAgentExecutor`) and a `TaskStore` (here, `InMemoryTaskStore`). 20 | - It routes incoming A2A RPC calls to the appropriate methods on your executor (like `execute` or `cancel`). 21 | - The `TaskStore` is used by the `DefaultRequestHandler` to manage the lifecycle of tasks, especially for stateful interactions, streaming, and resubscription. Even if your agent executor is simple, the handler needs a task store. 22 | 23 | 2. **`A2AStarletteApplication`**: 24 | 25 | - The `A2AStarletteApplication` class is instantiated with the `agent_card` and the `request_handler` (referred to as `http_handler` in its constructor). 26 | - The `agent_card` is crucial because the server will expose it at the `/.well-known/agent.json` endpoint (by default). 27 | - The `request_handler` is responsible for processing all incoming A2A method calls by interacting with your `AgentExecutor`. 28 | 29 | 3. **`uvicorn.run(server_app_builder.build(), ...)`**: 30 | - The `A2AStarletteApplication` has a `build()` method that constructs the actual Starlette application. 31 | - This application is then run using `uvicorn.run()`, making your agent accessible over HTTP. 32 | - `host='0.0.0.0'` makes the server accessible on all network interfaces on your machine. 33 | - `port=9999` specifies the port to listen on. This matches the `url` in the `AgentCard`. 34 | 35 | ## Running the Helloworld Server 36 | 37 | Navigate to the `a2a-samples` directory in your terminal (if you're not already there) and ensure your virtual environment is activated. 38 | 39 | To run the Helloworld server: 40 | 41 | ```bash 42 | # from the a2a-samples directory 43 | python samples/python/agents/helloworld/__main__.py 44 | ``` 45 | 46 | You should see output similar to this, indicating the server is running: 47 | 48 | ```console { .no-copy } 49 | INFO: Started server process [xxxxx] 50 | INFO: Waiting for application startup. 51 | INFO: Application startup complete. 52 | INFO: Uvicorn running on http://0.0.0.0:9999 (Press CTRL+C to quit) 53 | ``` 54 | 55 | Your A2A Helloworld agent is now live and listening for requests! In the next step, we'll interact with it. 56 | -------------------------------------------------------------------------------- /docs/tutorials/python/6-interact-with-server.md: -------------------------------------------------------------------------------- 1 | # 6. Interacting with the Server 2 | 3 | With the Helloworld A2A server running, let's send some requests to it. The SDK includes a client (`A2AClient`) that simplifies these interactions. 4 | 5 | ## The Helloworld Test Client 6 | 7 | The `test_client.py` script demonstrates how to: 8 | 9 | 1. Fetch the Agent Card from the server. 10 | 2. Create an `A2AClient` instance. 11 | 3. Send both non-streaming (`message/send`) and streaming (`message/stream`) requests. 12 | 13 | Open a **new terminal window**, activate your virtual environment, and navigate to the `a2a-samples` directory. 14 | 15 | Activate virtual environment (Be sure to do this in the same directory where you created the virtual environment): 16 | 17 | === "Mac/Linux" 18 | 19 | ```sh 20 | source .venv/bin/activate 21 | ``` 22 | 23 | === "Windows" 24 | 25 | ```powershell 26 | .venv\Scripts\activate 27 | ``` 28 | 29 | Run the test client: 30 | 31 | ```bash 32 | # from the a2a-samples directory 33 | python samples/python/agents/helloworld/test_client.py 34 | ``` 35 | 36 | ## Understanding the Client Code 37 | 38 | Let's look at key parts of `test_client.py`: 39 | 40 | 1. **Fetching the Agent Card & Initializing the Client**: 41 | 42 | ```python { .no-copy } 43 | --8<-- "https://raw.githubusercontent.com/google-a2a/a2a-samples/refs/heads/main/samples/python/agents/helloworld/test_client.py:A2ACardResolver" 44 | ``` 45 | 46 | The `A2ACardResolver` class is a convenience. It first fetches the `AgentCard` from the server's `/.well-known/agent.json` endpoint (based on the provided base URL) and then initializes the client with it. 47 | 48 | 2. **Sending a Non-Streaming Message (`send_message`)**: 49 | 50 | ```python { .no-copy } 51 | --8<-- "https://raw.githubusercontent.com/google-a2a/a2a-samples/refs/heads/main/samples/python/agents/helloworld/test_client.py:send_message" 52 | ``` 53 | 54 | - The `send_message_payload` constructs the data for `MessageSendParams`. 55 | - This is wrapped in a `SendMessageRequest`. 56 | - It includes a `message` object with the `role` set to "user" and the content in `parts`. 57 | - The Helloworld agent's `execute` method will enqueue a single "Hello World" message. The `DefaultRequestHandler` will retrieve this and send it as the response. 58 | - The `response` will be a `SendMessageResponse` object, which contains either a `SendMessageSuccessResponse` (with the agent's `Message` as the result) or a `JSONRPCErrorResponse`. 59 | 60 | 3. **Handling Task IDs (Illustrative Note for Helloworld)**: 61 | 62 | The Helloworld client (`test_client.py`) doesn't attempt `get_task` or `cancel_task` directly because the simple Helloworld agent's `execute` method, when called via `message/send`, results in the `DefaultRequestHandler` returning a direct `Message` response rather than a `Task` object. More complex agents that explicitly manage tasks (like the LangGraph example) would return a `Task` object from `message/send`, and its `id` could then be used for `get_task` or `cancel_task`. 63 | 64 | 4. **Sending a Streaming Message (`send_message_streaming`)**: 65 | 66 | ```python { .no-copy } 67 | --8<-- "https://raw.githubusercontent.com/google-a2a/a2a-samples/refs/heads/main/samples/python/agents/helloworld/test_client.py:send_message_streaming" 68 | ``` 69 | 70 | - This method calls the agent's `message/stream` endpoint. The `DefaultRequestHandler` will invoke the `HelloWorldAgentExecutor.execute` method. 71 | - The `execute` method enqueues one "Hello World" message, and then the event queue is closed. 72 | - The client will receive this single message as one `SendStreamingMessageResponse` event, and then the stream will terminate. 73 | - The `stream_response` is an `AsyncGenerator`. 74 | 75 | ## Expected Output 76 | 77 | When you run `test_client.py`, you'll see JSON outputs for: 78 | 79 | - The non-streaming response (a single "Hello World" message). 80 | - The streaming response (a single "Hello World" message as one chunk, after which the stream ends). 81 | 82 | The `id` fields in the output will vary with each run. 83 | 84 | ```console { .no-copy } 85 | // Non-streaming response 86 | {"jsonrpc":"2.0","id":"xxxxxxxx","result":{"type":"message","role":"agent","parts":[{"type":"text","text":"Hello World"}],"messageId":"yyyyyyyy"}} 87 | // Streaming response (one chunk) 88 | {"jsonrpc":"2.0","id":"zzzzzzzz","result":{"type":"message","role":"agent","parts":[{"type":"text","text":"Hello World"}],"messageId":"wwwwwwww","final":true}} 89 | ``` 90 | 91 | _(Actual IDs like `xxxxxxxx`, `yyyyyyyy`, `zzzzzzzz`, `wwwwwwww` will be different UUIDs/request IDs)_ 92 | 93 | This confirms your server is correctly handling basic A2A interactions with the updated SDK structure! 94 | 95 | Now you can shut down the server by typing Ctrl+C in the terminal window where `__main__.py` is running. 96 | -------------------------------------------------------------------------------- /docs/tutorials/python/7-streaming-and-multiturn.md: -------------------------------------------------------------------------------- 1 | # 7. Streaming & Multi-Turn Interactions (LangGraph Example) 2 | 3 | The Helloworld example demonstrates the basic mechanics of A2A. For more advanced features like robust streaming, task state management, and multi-turn conversations powered by an LLM, we'll turn to the LangGraph example located in [`a2a-samples/samples/python/agents/langgraph/`](https://github.com/google-a2a/a2a-samples/tree/main/samples/python/agents/langgraph). 4 | 5 | This example features a "Currency Agent" that uses the Gemini model via LangChain and LangGraph to answer currency conversion questions. 6 | 7 | ## Setting up the LangGraph Example 8 | 9 | 1. Create a [Gemini API Key](https://ai.google.dev/gemini-api/docs/api-key), if you don't already have one. 10 | 11 | 2. **Environment Variable:** 12 | 13 | Create a `.env` file in the `a2a-samples/samples/python/agents/langgraph/` directory: 14 | 15 | ```bash 16 | echo "GOOGLE_API_KEY=YOUR_API_KEY_HERE" > .env 17 | ``` 18 | 19 | Replace `YOUR_API_KEY_HERE` with your actual Gemini API key. 20 | 21 | 3. **Install Dependencies (if not already covered):** 22 | 23 | The `langgraph` example has its own `pyproject.toml` which includes dependencies like `langchain-google-genai` and `langgraph`. When you installed the SDK from the `a2a-samples` root using `pip install -e .[dev]`, this should have also installed the dependencies for the workspace examples, including `langgraph-example`. If you encounter import errors, ensure your primary SDK installation from the root directory was successful. 24 | 25 | ## Running the LangGraph Server 26 | 27 | Navigate to the `a2a-samples/samples/python/agents/langgraph/app` directory in your terminal and ensure your virtual environment (from the SDK root) is activated. 28 | 29 | Start the LangGraph agent server: 30 | 31 | ```bash 32 | python __main__.py 33 | ``` 34 | 35 | This will start the server, usually on `http://localhost:10000`. 36 | 37 | ## Interacting with the LangGraph Agent 38 | 39 | Open a **new terminal window**, activate your virtual environment, and navigate to `a2a-samples/samples/python/agents/langgraph/app`. 40 | 41 | Run its test client: 42 | 43 | ```bash 44 | python test_client.py 45 | ``` 46 | 47 | Now, you can shut down the server by typing Ctrl+C in the terminal window where `__main__.py` is running. 48 | 49 | ## Key Features Demonstrated 50 | 51 | The `langgraph` example showcases several important A2A concepts: 52 | 53 | 1. **LLM Integration**: 54 | 55 | - `agent.py` defines `CurrencyAgent`. It uses `ChatGoogleGenerativeAI` and LangGraph's `create_react_agent` to process user queries. 56 | - This demonstrates how a real LLM can power the agent's logic. 57 | 58 | 2. **Task State Management**: 59 | 60 | - `samples/langgraph/__main__.py` initializes a `DefaultRequestHandler` with an `InMemoryTaskStore`. 61 | 62 | ```python { .no-copy } 63 | --8<-- "https://raw.githubusercontent.com/google-a2a/a2a-samples/refs/heads/main/samples/python/agents/langgraph/app/__main__.py:DefaultRequestHandler" 64 | ``` 65 | 66 | - The `CurrencyAgentExecutor` (in `samples/langgraph/agent_executor.py`), when its `execute` method is called by the `DefaultRequestHandler`, interacts with the `RequestContext` which contains the current task (if any). 67 | - For `message/send`, the `DefaultRequestHandler` uses the `TaskStore` to persist and retrieve task state across interactions. The response to `message/send` will be a full `Task` object if the agent's execution flow involves multiple steps or results in a persistent task. 68 | - The `test_client.py`'s `run_single_turn_test` demonstrates getting a `Task` object back and then querying it using `get_task`. 69 | 70 | 3. **Streaming with `TaskStatusUpdateEvent` and `TaskArtifactUpdateEvent`**: 71 | 72 | - The `execute` method in `CurrencyAgentExecutor` is responsible for handling both non-streaming and streaming requests, orchestrated by the `DefaultRequestHandler`. 73 | - As the LangGraph agent processes the request (which might involve calling tools like `get_exchange_rate`), the `CurrencyAgentExecutor` enqueues different types of events onto the `EventQueue`: 74 | - `TaskStatusUpdateEvent`: For intermediate updates (e.g., "Looking up exchange rates...", "Processing the exchange rates.."). The `final` flag on these events is `False`. 75 | - `TaskArtifactUpdateEvent`: When the final answer is ready, it's enqueued as an artifact. The `lastChunk` flag is `True`. 76 | - A final `TaskStatusUpdateEvent` with `state=TaskState.completed` and `final=True` is sent to signify the end of the task for streaming. 77 | - The `test_client.py`'s `run_streaming_test` function will print these individual event chunks as they are received from the server. 78 | 79 | 4. **Multi-Turn Conversation (`TaskState.input_required`)**: 80 | 81 | - The `CurrencyAgent` can ask for clarification if a query is ambiguous (e.g., user asks "how much is 100 USD?"). 82 | - When this happens, the `CurrencyAgentExecutor` will enqueue a `TaskStatusUpdateEvent` where `status.state` is `TaskState.input_required` and `status.message` contains the agent's question (e.g., "To which currency would you like to convert?"). This event will have `final=True` for the current interaction stream. 83 | - The `test_client.py`'s `run_multi_turn_test` function demonstrates this: 84 | - It sends an initial ambiguous query. 85 | - The agent responds (via the `DefaultRequestHandler` processing the enqueued events) with a `Task` whose status is `input_required`. 86 | - The client then sends a second message, including the `taskId` and `contextId` from the first turn's `Task` response, to provide the missing information ("in GBP"). This continues the same task. 87 | 88 | ## Exploring the Code 89 | 90 | Take some time to look through these files: 91 | 92 | - `__main__.py`: Server setup using `A2AStarletteApplication` and `DefaultRequestHandler`. Note the `AgentCard` definition includes `capabilities.streaming=True`. 93 | - `agent.py`: The `CurrencyAgent` with LangGraph, LLM model, and tool definitions. 94 | - `agent_executor.py`: The `CurrencyAgentExecutor` implementing the `execute` (and `cancel`) method. It uses the `RequestContext` to understand the ongoing task and the `EventQueue` to send back various events (`TaskStatusUpdateEvent`, `TaskArtifactUpdateEvent`, new `Task` object implicitly via the first event if no task exists). 95 | - `test_client.py`: Demonstrates various interaction patterns, including retrieving task IDs and using them for multi-turn conversations. 96 | 97 | This example provides a much richer illustration of how A2A facilitates complex, stateful, and asynchronous interactions between agents. 98 | -------------------------------------------------------------------------------- /docs/tutorials/python/8-next-steps.md: -------------------------------------------------------------------------------- 1 | # Next Steps 2 | 3 | Congratulations on completing the A2A Python SDK Tutorial! You've learned how to: 4 | 5 | - Set up your environment for A2A development. 6 | - Define Agent Skills and Agent Cards using the SDK's types. 7 | - Implement a basic HelloWorld A2A server and client. 8 | - Understand and implement streaming capabilities. 9 | - Integrate a more complex agent using LangGraph, demonstrating task state management and tool use. 10 | 11 | You now have a solid foundation for building and integrating your own A2A-compliant agents. 12 | 13 | ## Where to Go From Here? 14 | 15 | Here are some ideas and resources to continue your A2A journey: 16 | 17 | - **Explore Other Examples:** 18 | - Check out the other examples in the `a2a-samples/samples/` directory in the [A2A GitHub repository](https://github.com/google-a2a/a2a-samples/tree/main/examples) for more complex agent integrations and features. 19 | - The main A2A repository also has [samples for other languages and frameworks](https://github.com/google-a2a/A2A/tree/main/samples). 20 | - **Deepen Your Protocol Understanding:** 21 | - 📚 Read the complete [A2A Protocol Documentation site](https://google.github.io/A2A/) for a comprehensive overview. 22 | - 📝 Review the detailed [A2A Protocol Specification](../../specification.md) to understand the nuances of all data structures and RPC methods. 23 | - **Review Key A2A Topics:** 24 | - [A2A and MCP](../../topics/a2a-and-mcp.md): Understand how A2A complements the Model Context Protocol for tool usage. 25 | - [Enterprise-Ready Features](../../topics/enterprise-ready.md): Learn about security, observability, and other enterprise considerations. 26 | - [Streaming & Asynchronous Operations](../../topics/streaming-and-async.md): Get more details on SSE and push notifications. 27 | - [Agent Discovery](../../topics/agent-discovery.md): Explore different ways agents can find each other. 28 | - **Build Your Own Agent:** 29 | - Try creating a new A2A agent using your favorite Python agent framework (like LangChain, CrewAI, AutoGen, Semantic Kernel, or a custom solution). 30 | - Implement the `a2a.server.AgentExecutor` interface to bridge your agent's logic with the A2A protocol. 31 | - Think about what unique skills your agent could offer and how its Agent Card would represent them. 32 | - **Experiment with Advanced Features:** 33 | - Implement robust task management with a persistent `TaskStore` if your agent handles long-running or multi-session tasks. 34 | - Explore implementing push notifications if your agent's tasks are very long-lived. 35 | - Consider more complex input and output modalities (e.g., handling file uploads/downloads, or structured data via `DataPart`). 36 | - **Contribute to the A2A Community:** 37 | - Join the discussions on the [A2A GitHub Discussions page](https://github.com/google-a2a/A2A/discussions). 38 | - Report issues or suggest improvements via [GitHub Issues](https://github.com/google-a2a/A2A/issues). 39 | - Consider contributing code, examples, or documentation. See the [CONTRIBUTING.md](https://github.com/google-a2a/A2A/blob/main/CONTRIBUTING.md) guide. 40 | 41 | The A2A protocol aims to foster an ecosystem of interoperable AI agents. By building and sharing A2A-compliant agents, you can be a part of this exciting development! 42 | -------------------------------------------------------------------------------- /lychee.toml: -------------------------------------------------------------------------------- 1 | exclude = [ 2 | 'https://fonts.gstatic.com/', 3 | 'https://fonts.googleapis.com/', 4 | 'http://go/github', 5 | 'http://go/github-googlecloudplatform', 6 | 'https://medium.com/', 7 | 'https://x.com/', 8 | 'http://localhost:12000/', 9 | 'http://localhost:10020/', 10 | 'https://www.askmarvin.ai/', 11 | 'https://www.bcg.com/', 12 | 'https://www.oracle.com/netsuite', 13 | 'https://www.spglobal.com/', 14 | 'https://www.epam.com/', 15 | 'https://www.servicenow.com/', 16 | ] 17 | exclude_path = [ 18 | ".github/actions/spelling", 19 | ] 20 | 21 | max_retries = 0 22 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | # Project information 2 | site_name: Agent2Agent Protocol (A2A) 3 | site_url: https://google.github.io/A2A/ 4 | site_description: >- 5 | An open protocol enabling communication and interoperability between opaque agentic applications. 6 | site_dir: site 7 | 8 | # Navigation 9 | nav: 10 | - Home: index.md 11 | - Topics: 12 | - What is A2A?: topics/what-is-a2a.md 13 | - Key Concepts: topics/key-concepts.md 14 | - A2A and MCP: topics/a2a-and-mcp.md 15 | - Agent Discovery: topics/agent-discovery.md 16 | - Enterprise-Ready Features: topics/enterprise-ready.md 17 | - Streaming & Asynchronous Operations: topics/streaming-and-async.md 18 | - Specification: specification.md 19 | - Community: community.md 20 | - Partners: partners.md 21 | - SDK Reference: 22 | - Python: sdk/python/index.md 23 | - Tutorial (Python): 24 | - Introduction: tutorials/python/1-introduction.md 25 | - Setup: tutorials/python/2-setup.md 26 | - Agent Skills & Agent Card: tutorials/python/3-agent-skills-and-card.md 27 | - Agent Executor: tutorials/python/4-agent-executor.md 28 | - Start Server: tutorials/python/5-start-server.md 29 | - Interact with Server: tutorials/python/6-interact-with-server.md 30 | - Streaming & Multiturn: tutorials/python/7-streaming-and-multiturn.md 31 | - Next Steps: tutorials/python/8-next-steps.md 32 | 33 | # Repository 34 | repo_name: google-a2a/A2A 35 | repo_url: https://github.com/google-a2a/A2A 36 | 37 | # Copyright 38 | copyright: Copyright Google 2025 39 | 40 | # Custom CSS 41 | extra_css: 42 | - stylesheets/custom.css 43 | 44 | # Configuration 45 | theme: 46 | name: material 47 | font: 48 | text: Google Sans 49 | code: Roboto Mono 50 | logo: assets/a2a-logo-white.svg 51 | favicon: assets/a2a-logo-black.svg 52 | icon: 53 | repo: fontawesome/brands/github 54 | palette: 55 | - scheme: default 56 | primary: indigo 57 | accent: white 58 | toggle: 59 | icon: material/brightness-7 60 | name: Switch to dark mode 61 | - scheme: slate 62 | primary: indigo 63 | accent: white 64 | toggle: 65 | icon: material/brightness-4 66 | name: Switch to light mode 67 | features: 68 | - content.code.annotate 69 | - content.code.copy 70 | - content.code.select 71 | - content.tabs.link 72 | - navigation.expand 73 | - navigation.footer 74 | - navigation.indexes 75 | - navigation.instant 76 | - navigation.instant.progress 77 | - navigation.path 78 | - navigation.tabs 79 | - navigation.top 80 | - navigation.tracking 81 | - toc.follow 82 | 83 | # Extensions 84 | markdown_extensions: 85 | - admonition 86 | - attr_list 87 | - md_in_html 88 | - pymdownx.details 89 | - pymdownx.emoji: 90 | emoji_index: !!python/name:material.extensions.emoji.twemoji 91 | emoji_generator: !!python/name:material.extensions.emoji.to_svg 92 | - pymdownx.highlight: 93 | anchor_linenums: true 94 | line_spans: __span 95 | pygments_lang_class: true 96 | - pymdownx.inlinehilite 97 | - pymdownx.snippets: 98 | url_download: true 99 | dedent_subsections: true 100 | - pymdownx.superfences: 101 | custom_fences: 102 | - name: mermaid 103 | class: mermaid 104 | format: !!python/name:pymdownx.superfences.fence_code_format 105 | - pymdownx.tabbed: 106 | alternate_style: true 107 | slugify: !!python/object/apply:pymdownx.slugs.slugify 108 | kwds: 109 | case: lower 110 | - toc: 111 | permalink: true 112 | 113 | # Plugins 114 | plugins: 115 | - search 116 | - redirects: 117 | redirect_maps: 118 | "spec-json.md": https://raw.githubusercontent.com/google-a2a/A2A/refs/heads/main/specification/json/a2a.json 119 | "specification/overview.md": "specification.md" 120 | "specification/agent-card.md": "specification.md#5-agent-discovery-the-agent-card" 121 | "specification/agent-to-agent-communication.md": "specification.md#6-protocol-data-objects" 122 | "specification/sample-messages.md": "specification.md#9-common-workflows-examples" 123 | "specification/details.md": "specification.md" 124 | "documentation.md": "topics/key-concepts.md" 125 | "resources.md": "index.md" 126 | "topics/push-notifications.md": "topics/streaming-and-async.md" 127 | "specification/topics/a2a_and_mcp.md": "topics/a2a-and-mcp.md" 128 | "specification/topics/agent_discovery.md": "topics/agent-discovery.md" 129 | "specification/topics/enterprise_ready.md": "topics/enterprise-ready.md" 130 | "specification/topics/push_notification.md": "topics/streaming-and-async.md" 131 | "specification/topics/push_notifications.md": "topics/streaming-and-async.md" 132 | "topics/index.md": "topics/what-is-a2a.md" 133 | # Tutorial 134 | "tutorials/index.md": "tutorials/python/1-introduction.md" 135 | "tutorials/python/index.md": "tutorials/python/1-introduction.md" 136 | "tutorials/python/1_introduction.md": "tutorials/python/1-introduction.md" 137 | "tutorials/python/3-create-project.md": "tutorials/python/2-setup.md" 138 | "tutorials/python/4-agent-skills.md": "tutorials/python/3-agent-skills-and-card.md" 139 | "tutorials/python/5-add-agent-card.md": "tutorials/python/3-agent-skills-and-card.md" 140 | "tutorials/python/6-start-server.md": "tutorials/python/5-start-server.md" 141 | "tutorials/python/7-interact-with-server.md": "tutorials/python/6-interact-with-server.md" 142 | "tutorials/python/8-agent-capabilities.md": "tutorials/python/7-streaming-and-multiturn.md" 143 | "tutorials/python/9-ollama-agent.md": "tutorials/python/7-streaming-and-multiturn.md" 144 | "tutorials/python/10-next-steps.md": "tutorials/python/8-next-steps.md" 145 | - mkdocstrings: 146 | handlers: 147 | python: 148 | options: 149 | show_root_heading: false 150 | show_object_full_path: false 151 | show_value: true 152 | show_if_no_docstring: true 153 | filters: ["!^_"] 154 | show_qualifiers: false 155 | -------------------------------------------------------------------------------- /noxfile.py: -------------------------------------------------------------------------------- 1 | # pylint: skip-file 2 | # type: ignore 3 | # -*- coding: utf-8 -*- 4 | # 5 | # Copyright 2025 Google LLC 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | import os 20 | import pathlib 21 | import subprocess 22 | 23 | import nox 24 | 25 | 26 | DEFAULT_PYTHON_VERSION = '3.11' 27 | 28 | CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute() 29 | 30 | nox.options.sessions = [ 31 | 'format', 32 | ] 33 | 34 | # Error if a python version is missing 35 | nox.options.error_on_missing_interpreters = True 36 | 37 | 38 | @nox.session(python=DEFAULT_PYTHON_VERSION) 39 | def format(session): 40 | """Format Python code using autoflake, pyupgrade, and ruff.""" 41 | # Sort Spelling Allowlist 42 | spelling_allow_file = '.github/actions/spelling/allow.txt' 43 | 44 | with open(spelling_allow_file, encoding='utf-8') as file: 45 | unique_words = sorted(set(file)) 46 | 47 | with open(spelling_allow_file, 'w', encoding='utf-8') as file: 48 | file.writelines(unique_words) 49 | 50 | format_all = False 51 | 52 | if format_all: 53 | lint_paths_py = ['.'] 54 | else: 55 | target_branch = 'origin/main' 56 | 57 | unstaged_files = subprocess.run( 58 | [ 59 | 'git', 60 | 'diff', 61 | '--name-only', 62 | '--diff-filter=ACMRTUXB', 63 | target_branch, 64 | ], 65 | stdout=subprocess.PIPE, 66 | text=True, 67 | check=False, 68 | ).stdout.splitlines() 69 | 70 | staged_files = subprocess.run( 71 | [ 72 | 'git', 73 | 'diff', 74 | '--cached', 75 | '--name-only', 76 | '--diff-filter=ACMRTUXB', 77 | target_branch, 78 | ], 79 | stdout=subprocess.PIPE, 80 | text=True, 81 | check=False, 82 | ).stdout.splitlines() 83 | 84 | committed_files = subprocess.run( 85 | [ 86 | 'git', 87 | 'diff', 88 | 'HEAD', 89 | target_branch, 90 | '--name-only', 91 | '--diff-filter=ACMRTUXB', 92 | ], 93 | stdout=subprocess.PIPE, 94 | text=True, 95 | check=False, 96 | ).stdout.splitlines() 97 | 98 | changed_files = sorted( 99 | { 100 | file 101 | for file in (unstaged_files + staged_files + committed_files) 102 | if os.path.isfile(file) 103 | } 104 | ) 105 | 106 | lint_paths_py = [f for f in changed_files if f.endswith('.py')] 107 | 108 | if not lint_paths_py: 109 | session.log('No changed Python files to lint.') 110 | return 111 | 112 | session.install( 113 | 'types-requests', 114 | 'pyupgrade', 115 | 'autoflake', 116 | 'ruff', 117 | ) 118 | 119 | if lint_paths_py: 120 | if not format_all: 121 | session.run( 122 | 'pyupgrade', 123 | '--exit-zero-even-if-changed', 124 | '--py311-plus', 125 | *lint_paths_py, 126 | ) 127 | session.run( 128 | 'autoflake', 129 | '-i', 130 | '-r', 131 | '--remove-all-unused-imports', 132 | *lint_paths_py, 133 | ) 134 | session.run( 135 | 'ruff', 136 | 'check', 137 | '--fix-only', 138 | *lint_paths_py, 139 | ) 140 | session.run( 141 | 'ruff', 142 | 'format', 143 | *lint_paths_py, 144 | ) 145 | -------------------------------------------------------------------------------- /requirements-docs.txt: -------------------------------------------------------------------------------- 1 | mkdocs-material==9.6.12 2 | mkdocs-redirects==1.2.2 3 | mkdocstrings[python] 4 | -------------------------------------------------------------------------------- /specification/json/README.md: -------------------------------------------------------------------------------- 1 | # A2A Specification JSON 2 | 3 | DO NOT EDIT `a2a.json` directly. 4 | 5 | Make all edits in [`types/src/types.ts`](https://github.com/google-a2a/A2A/blob/main/types/src/types.ts) and follow the directions in [`types/README.md`](https://github.com/google-a2a/A2A/blob/main/types/README.md) 6 | -------------------------------------------------------------------------------- /types/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /types/README.md: -------------------------------------------------------------------------------- 1 | # A2A Types 2 | 3 | Core objects and method types for A2A Protocol 4 | 5 | ## Steps to update 6 | 7 | 1. Clone this repository. 8 | 2. Run `npm install` 9 | 3. Update `types.ts` with required changes 10 | 4. Run `npm run generate`, this will update `a2a.json`. 11 | 5. Verify the updates and push to the repository. 12 | 13 | **DO NOT DIRECTLY CHANGE `a2a.json` file. THIS MUST BE GENERATED USING `npm run generate`** 14 | -------------------------------------------------------------------------------- /types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "types", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "generate": "./node_modules/.bin/typescript-json-schema tsconfig.json \"*\" --defaultNumberType integer --required > ../specification/json/a2a.json" 7 | }, 8 | "author": "", 9 | "description": "A2A Types", 10 | "dependencies": { 11 | "typescript-json-schema": "^0.65.1" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.3.3" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noEmit": true, 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "target": "ES5", 7 | "module": "CommonJS", 8 | "strictNullChecks": false, 9 | "skipLibCheck": true 10 | }, 11 | "include": ["**/*.ts"], 12 | "exclude": ["node_modules"] 13 | } 14 | --------------------------------------------------------------------------------