A2A support is in preview. It’s available to every account with no extra rate limits, but the surface may still change. Prefer native Python without a protocol layer? The DataLinks Python SDK has its own
ask API.Prerequisites
Before starting, make sure you have:- A DataLinks API token. See Get an API token. The same token you use for the REST API and SDK works for A2A.
- The namespace you want the agent to work against. You can find it under My Data.
- Python 3.10+ (this guide uses the official
a2a-sdkclient; any A2A-compliant client works).
Install Required Dependencies
The reference client uses the official A2A Python SDK and an async HTTP client:Configure Your Environment
The client reads standard DataLinks settings from the environment (or a.env file):
DL_HOST- the DataLinks host that serves the A2A endpoints:https://api.datalinks.com/api/v1DL_API_KEY- your DataLinks API tokenDL_NAMESPACE- the namespace the agent should queryDL_A2A_AGENT- (optional) the agent to use; defaults to the first agent listed by the server
Alternatively, place these values in a
.env file at the root of your project.How the DataLinks A2A Endpoints Work
A2A lives under the API base URL. WithDL_HOST set to https://api.datalinks.com/api/v1, DataLinks exposes every agent through three endpoints:
| Endpoint | Auth | Purpose |
|---|---|---|
GET {host}/a2a | Public | List the agents this server exposes |
GET {host}/a2a/{agent}/.well-known/agent-card.json | Public | Fetch the agent’s AgentCard (capabilities and security scheme) |
POST {host}/a2a/{agent} | Bearer token | Send messages (JSON-RPC, streaming) |
| Agent | What it does |
|---|---|
nl2ql | Turns a plain-language question into a structured query, runs it against your namespace, and returns the generated query plus the result rows. |
assistant | Plans a multi-step query strategy, runs the queries, and synthesises an answer. This is the same assistant behind the ask endpoint. |
Connect and Ask a Question
The flow has five steps: discover agents, resolve the chosen agent’s card, register your API key as the bearer credential, send the message with the target namespace, and stream the answer.Resolve the AgentCard and register credentials
Your API key is sent as a bearer token for whatever security scheme(s) the card declares (DataLinks declares a single scheme named Iterating over the card’s declared schemes (rather than hardcoding
bearer, sent as Bearer <key>)."bearer") keeps your client working if the scheme name ever changes.Send the message with the target namespace
The namespace travels in the message metadata; the server reads
message.metadata.namespace. You can optionally add model and provider to the same metadata to steer which LLM the agent uses.Handling the Streamed Response
A2A streaming yields a sequence of typed events, not a single answer. Each event’spayload is one of task, message, status_update, or artifact_update. Within a message or artifact, the content arrives as parts, and each part is either a TextPart or a DataPart.
The two agents return their results as named artifacts:
nl2qlemits agenerated-queryartifact (the query, as aTextPart) and aresult-dataartifact (the rows, as aDataPart).assistantstreamsworkingstatus updates while it plans and runs steps, astep-Nartifact per step (the step’s query plus its rows), and a finalanswerartifact (the synthesised answer, as aTextPart).
Verify the Connection
To confirm everything is working:GET {host}/a2areturns a non-empty list of agents (nl2qlandassistant).- Fetching the AgentCard for your chosen agent succeeds.
- A simple question streams back a
status_updatereaching a completed state, followed by an answer. - No
401/403authorization errors appear.
Troubleshooting
Authorization errors (401 / 403)- Confirm your DataLinks API token is correct and current.
- Make sure the token is sent as
Bearer <token>with no extra spaces. - Confirm the scheme name you registered matches the one the AgentCard declares (
bearer).
- Confirm
DL_HOSTpoints athttps://api.datalinks.com/api/v1(A2A lives under the API base, not the root host).
message metadata.namespace is required
- The namespace must live in the message metadata (
message.metadata.namespace), not in the URL, the request-level metadata, or the body.
- You’re only handling
TextParts. HandleDataParts too (see the warning above); the rows arrive underpart.data.rows.
- Increase the HTTP client timeout; some agent runs take longer than the default.
- Confirm the
namespacein the message metadata exists, has at least one dataset, and you have access to it.
When to Use A2A, MCP, or the SDK
DataLinks offers three ways to reach the same data. Pick by how you’re building:| You want to… | Use |
|---|---|
| Talk to a DataLinks agent as a peer, from any A2A-compliant framework | A2A (this guide) |
| Expose DataLinks as a tool inside an AI client (Claude Desktop, IDEs, agent frameworks that speak MCP) | MCP |
| Write native Python with no protocol layer | Python SDK ask |
Next Steps
- Read the A2A Protocol Reference for the full endpoint, AgentCard, and event details.
- Try the complete runnable client.
- Combine the agent’s answers with your own workflow or multi-agent system.