An A2A (Agent-to-Agent) protocol server that wraps a Databricks AI/BI Genie room, deployed as a Databricks App.
Any A2A-compatible agent can discover this agent, ask natural language questions about the underlying data, and hold multi-turn conversations — all through the standard A2A protocol.
A2A Client ──HTTP/SSE──> Databricks App (A2A Server)
│
├── /.well-known/agent-card.json (discovery)
├── POST / (JSON-RPC)
│
└── Genie Conversation API
│
└── Unity Catalog Tables
- Client discovers the agent via the Agent Card at
/.well-known/agent-card.json - Client sends a natural language question via
message/send(sync) ormessage/stream(SSE) - The server forwards the question to the Genie Conversation API
- Genie generates SQL, executes it, and returns a narrative + data
- The server returns the result as an A2A response with artifacts
Multi-turn conversations are supported by mapping the A2A contextId to a Genie conversation_id. Follow-up questions on the same contextId reuse the Genie conversation, so Genie retains full context (e.g., "break that down by region" after asking about total sales).
Implements the A2A v0.3.0 specification:
| A2A Method | Description |
|---|---|
message/send |
Synchronous request/response |
message/stream |
SSE streaming with TaskStatusUpdateEvent and TaskArtifactUpdateEvent |
All response types use the kind discriminator field as required by the spec.
- A Databricks workspace with:
- A Genie space configured with tables
- A SQL warehouse for the Genie space
- Databricks CLI authenticated (
databricks auth login)
app.py # A2A server + Genie bridge
app.yaml # Databricks App configuration
deploy.sh # Automated deploy script
requirements.txt # Python dependencies
test_client.py # Test client for verification
1. Install the Databricks CLI (if you don't have it):
# macOS
brew tap databricks/tap && brew install databricks
# Or via pip
pip install databricks-cliSee the install docs for other platforms.
2. Authenticate with your workspace:
databricks auth login --profile <your-profile> --host https://<your-workspace>.cloud.databricks.comThis opens a browser for OAuth login. Verify it worked:
databricks auth token --profile <your-profile>3. Get your Genie space ID:
Open a Genie room in your workspace. The space ID is the last segment of the URL:
https://<your-workspace>.cloud.databricks.com/genie/rooms/<SPACE-ID>
If you don't have a Genie room yet, create one in the workspace UI (AI/BI > Genie > New), point it at some tables, then grab the ID.
git clone <this-repo> && cd a2a
./deploy.sh --profile <your-profile> --genie-space-id <your-space-id>The script creates the app, uploads files, starts compute, deploys, and prints the permission-grant commands you need to run.
| Flag | Required | Default | Description |
|---|---|---|---|
--profile <name> |
Yes | — | Databricks CLI profile |
--genie-space-id <id> |
Yes | — | Genie space ID (from the room URL) |
--app-name <name> |
No | genie-a2a-agent |
Databricks App name |
--agent-name <name> |
No | Genie A2A Agent |
Display name in the A2A agent card |
--agent-description <text> |
No | Generic description | Agent description in the A2A card |
--skill-description <text> |
No | Generic description | Skill description in the A2A card |
All configuration is via environment variables set in app.yaml (or passed through deploy.sh flags):
| Variable | Required | Default | Description |
|---|---|---|---|
GENIE_SPACE_ID |
Yes | — | Databricks Genie space ID |
AGENT_NAME |
No | Genie A2A Agent |
Agent name in the A2A card |
AGENT_DESCRIPTION |
No | Generic description | Agent description in the A2A card |
AGENT_SKILL_DESCRIPTION |
No | Generic description | Skill description in the A2A card |
pip install httpx databricks-sdk
# Local
python test_client.py
# Deployed app
python test_client.py https://<your-app-url>
# Explicit CLI profile
python test_client.py https://<your-app-url> --profile MY_PROFILERuns three tests: a new question, a follow-up (multi-turn), and a new context (isolation).
TOKEN=$(databricks auth token --profile <your-profile> | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
# Agent card
curl -s -H "Authorization: Bearer $TOKEN" https://<app-url>/.well-known/agent-card.json
# Ask a question
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
https://<app-url>/ \
-d '{"jsonrpc":"2.0","id":1,"method":"message/send","params":{"id":"t1","contextId":"ctx1","message":{"role":"user","parts":[{"kind":"text","text":"What are the total sales?"}]}}}'git clone https://github.com/a2aproject/a2a-inspector.git
cd a2a-inspector
docker compose upOpen http://localhost:3000, enter your app URL, and set the auth header to Authorization: Bearer <oauth-token>.
Note: OAuth tokens from databricks auth token expire in ~1 hour. Do not use third-party hosted inspectors with your token.
If you prefer to deploy step by step instead of using deploy.sh:
Edit app.yaml and set the GENIE_SPACE_ID:
env:
- name: GENIE_SPACE_ID
value: "<your-genie-space-id>"You can find the space ID in the Genie room URL: https://<workspace>/genie/rooms/<space-id>
databricks apps create genie-a2a-agent --description "A2A agent wrapping a Genie room" --no-compute --profile <your-profile>Note the service_principal_id and service_principal_client_id from the output.
The app runs as a service principal that needs access to:
Genie space (CAN_RUN):
curl -X PATCH "https://<workspace-url>/api/2.0/permissions/genie/<space-id>" \
-H "Authorization: Bearer $(databricks auth token --profile <your-profile> | python3 -c 'import sys,json; print(json.load(sys.stdin)["access_token"])')" \
-H "Content-Type: application/json" \
-d '{"access_control_list": [{"service_principal_name": "<service_principal_client_id>", "permission_level": "CAN_RUN"}]}'SQL warehouse (CAN_USE):
curl -X PATCH "https://<workspace-url>/api/2.0/permissions/warehouses/<warehouse-id>" \
-H "Authorization: Bearer $(databricks auth token --profile <your-profile> | python3 -c 'import sys,json; print(json.load(sys.stdin)["access_token"])')" \
-H "Content-Type: application/json" \
-d '{"access_control_list": [{"service_principal_name": "<service_principal_client_id>", "permission_level": "CAN_USE"}]}'Unity Catalog (USE_CATALOG, USE_SCHEMA, SELECT):
databricks grants update catalog <catalog> --json '{"changes": [{"principal": "<service_principal_client_id>", "add": ["USE_CATALOG"]}]}' --profile <your-profile>
databricks grants update schema <catalog>.<schema> --json '{"changes": [{"principal": "<service_principal_client_id>", "add": ["USE_SCHEMA", "SELECT"]}]}' --profile <your-profile># Upload source to workspace
databricks workspace mkdirs /Workspace/Users/<you>/apps/genie-a2a-agent --profile <your-profile>
for f in app.py app.yaml requirements.txt; do
databricks workspace import /Workspace/Users/<you>/apps/genie-a2a-agent/$f --file $f --format AUTO --overwrite --profile <your-profile>
done
# Start compute and deploy
databricks apps start genie-a2a-agent --profile <your-profile> --no-wait
# Wait for compute to be ACTIVE, then:
databricks apps deploy genie-a2a-agent --source-code-path "/Workspace/Users/<you>/apps/genie-a2a-agent" --profile <your-profile>databricks apps get genie-a2a-agent --profile <your-profile> -o json | python3 -c "import sys,json; print(json.load(sys.stdin)['url'])"The Databricks App requires authentication. Callers must pass a valid OAuth token (not a PAT) in the Authorization: Bearer <token> header. OAuth tokens can be obtained via databricks auth token.