# Calling the A2A agent

## Available bindings for A2A calls

All A2A calls go to one of the following bindings on the Textual host:

<table><thead><tr><th width="208.83984375" valign="top">Binding type</th><th width="223.54296875" valign="top">Endpoint</th><th valign="top">Description</th></tr></thead><tbody><tr><td valign="top">JSON-RPC</td><td valign="top"><code>POST /a2a</code></td><td valign="top"><p>The default binding.</p><p></p><p>Used by A2A v0.3 clients.</p></td></tr><tr><td valign="top">REST (HTTP+JSON)</td><td valign="top"><code>POST /a2a/v1/message:send</code><br><br><code>GET /a2a/v1/tasks/{id}</code></td><td valign="top">Only available when the protocol mode is either <code>both</code> or <code>v1_only</code>.</td></tr></tbody></table>

Both bindings require `Authorization: Bearer <token>`.

The  token can be either a Textual API key or an OAuth access token.

## Using a Textual API key

When you use a Textual API key, you put the key directly in the header.

API keys do not expire, but they can be revoked.

```bash
curl https://<host>/a2a \
  -H "Authorization: Bearer <api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id":      1,
    "method":  "message/send",
    "params": {
      "message": {
        "role":      "user",
        "messageId": "msg-1",
        "parts":     [{"kind": "text", "text": "/detect John Smith lives at 123 Main St."}]
      }
    }
  }'
```

## Using an OAuth2 access token

Drive the authorization-code flow against the OAuth2 endpoints advertised in the agent card, then use the resulting access token exactly like an API key.

OAuth2 access tokens live for one hour. They cannot be refreshed. When a token expires, re-run the authorization code flow.

### Authentication flow

#### Starting the request

{% code overflow="wrap" %}

```python
import base64, hashlib, secrets, urllib.parse, webbrowser
import requests

BASE   = "https://textual.example.com"
CLIENT = ("PyFXmPVxAx9hKL3", "CpWEPmPVxAx9hKL3NcP9XjqBz6_5JmQsL8kZx2gYaH0")  # (clientId, clientSecret)
REDIR  = "https://your-app.example.com/oauth/callback"
```

{% endcode %}

For a client from an A2A-compliant marketplace clients, steps to get the access code and generate the access token occur automatically. You can then [#make-the-call-to-a2a-with-the-access-token](#make-the-call-to-a2a-with-the-access-token "mention").

Otherwise, continue to [#get-an-access-code](#get-an-access-code "mention").

#### Get an access code

Next, redirect the user to /authorize to complete the approval and obtain the access code.

To use PKCE, send `code_challenge` + `code_challenge_method=S256.`

{% code overflow="wrap" %}

```python
verifier  = secrets.token_urlsafe(64)
challenge = base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest()).rstrip(b"=").decode()
params = {
    "response_type":         "code",
    "client_id":             CLIENT[0],
    "redirect_uri":          REDIR,
    "scope":                 "a2a",
    "state":                 secrets.token_urlsafe(16),
    "code_challenge":        challenge,
    "code_challenge_method": "S256",
}
webbrowser.open(f"{BASE}/api/v1/a2a/oauth/authorize?{urllib.parse.urlencode(params)}")
code = input("paste ?code=... from the redirect URL: ")
```

{% endcode %}

#### Obtain the access token

Next, exchange the access code for an access token.

To use PKCE, send the matching `code_verifier`.

{% code overflow="wrap" %}

```python
token = requests.post(
    f"{BASE}/api/v1/a2a/oauth/token",
    data={
        "grant_type":    "authorization_code",
        "code":          code,
        "redirect_uri":  REDIR,
        "code_verifier": verifier,
    },
    auth=CLIENT,  # HTTP Basic
).json()["access_token"]
```

{% endcode %}

#### Make the call to /a2a with the access token

Finally, you use the token to make the call to the agent in the same way as you would with an API key:

{% code overflow="wrap" %}

```python
resp = requests.post(
    f"{BASE}/a2a",
    headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"},
    json={
        "jsonrpc": "2.0", "id": 1, "method": "message/send",
        "params": {"message": {"role": "user", "messageId": "m1",
                               "parts": [{"kind": "text", "text": "/redact John Smith, SSN 123-45-6789"}]}}
    },
).json()
```

{% endcode %}

## Selecting the protocol version

In the header, to determine the version of the A2A protocol to use:

* To use the v1 format, send `A2A-Version: 1.0`
* To use the v.03 format, either
  * Send `A2A-Version: 0.3`
  * Do not provide a version in the header.

## Task lifecycle

Each task progress through the standard A2A states: `submitted` → `working` → `completed` / `failed` / `canceled`.

When you use `tasks/cancel` to cancel a `file-redact` task, the cancellation propagates to the underlying Textual job.

Once a a `pii-detect` or `pii-redact` task is completed, the cancellation has no effect.

Completed, failed, and canceled tasks are purged after `SOLAR_A2A_TASK_TTL_HOURS`. The default is 72 hours.

Active tasks are never purged.

## About the response

The response contains a task object with an `id` and a list of artifacts.

* For `pii-detect` and `pii-redact`, the artifact is inline.
* For `file-redact`, the task is asynchronous and the client polls or subscribes for the completion event.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tonic.ai/textual/textual-integrations/textual-a2a-agent/calling-the-a2a-agent.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
