- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
2 weeks ago
The other half of the story
Last week I shared how to expose ServiceNow AI Agents via Google A2A — ServiceNow as an A2A server, responding to external systems. That's one direction.
This article proves the opposite direction: ServiceNow as an A2A client (primary agent), discovering and invoking an external AI agent over the same open protocol. Tested end-to-end on a sandbox instance running Zurich Patch 7.
A2A Client (Primary Agent): A ServiceNow-native orchestrator that reads an external agent's Agent Card, attaches a runtime credential, and invokes it via A2A message/send — as if it were a local tool.
Together, these two articles close the loop: ServiceNow speaks A2A fluently in both directions.
Common misconceptions
| Misconception | Reality |
|---|---|
| "I need custom Script Includes to call an external agent." | OOTB. Discovery, credential handling, and invocation are all platform-native. |
| "The external agent must be cloud-hosted." | Any HTTPS-reachable endpoint works. Local + ngrok is enough for a PoC. |
| "A2A is a Google product." | A2A is now governed by the Linux Foundation (GA v1.0, March 2026). Google contributes, but the spec is vendor-neutral. |
| "A2A is HTTP streaming by default." | The spec supports three bindings (JSON-RPC 2.0, gRPC, HTTP+JSON). ServiceNow's implementation uses JSON-RPC and supports both synchronous and asynchronous modes (async requires a registered callback URL). HTTP streaming is not supported. |
| "Discovery and execution share one credential." | Two separate mechanisms — a platform Flow fetches the Agent Card, a Connection & Credential Alias carries runtime auth. |
How it works
The primary agent flow has two phases: discovery then execution.
- Discovery — ServiceNow calls the external agent's
/.well-known/agent-card.jsonendpoint (a platform Flow named External AI Agent Card - A2A Protocol handles the fetch). The card'sname,description,url,protocolVersion, andskillsauto-populate the external agent record. - Execution — The AI Agent Orchestrator reads the runtime URL + credentials from the Connection & Credential Alias attached to the agent record, then sends a JSON-RPC
message/sendPOST to the external agent.
End-to-end flow
| Step | Actor | Action |
|---|---|---|
| 1 | User | Asks a question in Testing Playground / Virtual Agent |
| 2 | AI Agent Orchestrator | Sends A2A message/send POST to the external agent URL |
| 3 | ngrok tunnel | Forwards request to localhost:8001 |
| 4 | ADK A2A server | Routes to the target agent |
| 5 | External agent (Gemini-backed) | Generates response |
| 6 | Response | Streams back through the same chain to ServiceNow |
| 7 | ServiceNow | Renders the answer to the user |
Where it lives on the platform
A2A Client support is part of AI Agent Fabric, introduced in Now Assist AI Agents 6.0.x (December 2025, Zurich Patch 4+). ServiceNow's implementation targets A2A protocol v0.3.
| Capability | Status (current Zurich patches) |
|---|---|
| Synchronous invocation | Supported |
| Authentication: OAuth + API Key | Supported |
| Asynchronous with callback URL | Supported (callback registered in sn_aia_external_agent_callback_registry) |
| HTTP streaming | Not supported |
| Parallel tasking | Not supported |
| Artifacts | Not supported |
Build it with minimal efforts
Prerequisites: Python 3.11, ngrok free account, Gemini API key (free tier), ServiceNow sandbox on Zurich Patch 4+ with sn_aia.external_agents.enabled = true.
1. Write the external agent (Google ADK)
agent.py
from google.adk import Agent
from google.adk.a2a.utils.agent_to_a2a import to_a2a
root_agent = Agent(
model='gemini-2.5-flash',
name='it_policy_advisor',
description='Answers IT security and compliance questions.',
instruction='You are an IT Policy Advisor. Keep answers concise.',
tools=[],
)
a2a_app = to_a2a(
root_agent,
host="<subdomain>.ngrok-free.dev",
port=443,
protocol="https",
)
Install: pip install "google-adk[a2a]"
2. Start ngrok and the ADK server
Open two terminals.
Terminal 1 — ngrok tunnel:
ngrok http 8001
Copy the forwarding URL (e.g., https://<subdomain>.ngrok-free.dev) and paste the subdomain into agent.py's host= field.
Terminal 2 — ADK server:
export GOOGLE_API_KEY="<your-gemini-api-key>" uvicorn agent:a2a_app --host 0.0.0.0 --port 8001
About the Gemini API key:
- Get a free key from Google AI Studio — no credit card required.
- The PoC uses
gemini-2.5-flash. Newly created keys may showlimit: 0for older models (e.g.,gemini-2.0-flash), butgemini-2.5-flashhas its own free-tier quota. - Verify the key works before starting the server:
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H 'Content-Type: application/json' \
-H 'X-goog-api-key: <YOUR_API_KEY>' \
-d '{"contents":[{"parts":[{"text":"Say hello"}]}]}'
A successful response returns JSON with candidates[0].content.parts[0].text. A 429 response means the key has no quota — regenerate the key or switch the model.
Why the host field matters: ServiceNow reads the Agent Card's url field for runtime invocation. If that field points to localhost, discovery works but execution fails.
Verify the Agent Card is served via the public URL:
curl -s https://<subdomain>.ngrok-free.dev/.well-known/agent-card.json | python3 -m json.tool
Confirm the url field in the response shows the ngrok HTTPS URL, not localhost.
3. Enable A2A on ServiceNow
AI Agent Studio > Settings > External AI agents
| Setting | Value |
|---|---|
| Allow ServiceNow to access External AI agents | ON (sets sn_aia.external_agents.enabled = true) |
| Communication mode | Synchronous |
Why Synchronous: Async mode requires a public callback URL registered in sn_aia_external_agent_callback_registry. Without one, invocations silently cancel with no error.
4. Create the External Agent
AI Agent Studio > Create and manage > AI agents > Add > External, then select Agent2Agent (A2A) protocol.
4a. Add a new provider
| Field | Value |
|---|---|
| Name | Google ADK |
| Discovery type | Well-Known URI / Direct Configuration |
| Agent card URL | https://<subdomain>.ngrok-free.dev/.well-known/agent-card.json |
The URL must include the full /.well-known/agent-card.json path. The base URL alone returns 405 Method Not Allowed and discovery fails.
4b. Discover the agent
Click Discover external AI agent. ServiceNow sends a GET to the Agent Card URL and the agent name, version, and state appear. Click the agent row → Activate → Continue.
4c. Define the specialty
- Description — auto-populated from the Agent Card
- Communication mode — Synchronous
- Advanced settings — defaults
4d. Add authentication (execution alias)
Click + Create new connection and credential alias.
| Field | Value |
|---|---|
| Name | IT Policy Advisor A2A |
| Authentication Type | API Key |
| Credential value | Placeholder, e.g. no-auth-poc |
The wizard creates an alias with Type = Connection and Credential and Connection type = HTTP (auto-set), plus a child credential record of type API Key holding the value above. The PoC agent does not validate credentials, but ServiceNow requires an execution alias to invoke any external A2A agent.
Two keys, two purposes:
Key Stored in Authenticates External-agent API Key ServiceNow api_key_credentialstable (child of this Connection & Credential Alias)ServiceNow → external A2A agent Gemini API key Developer workstation env var GOOGLE_API_KEY(set in Step 2)External agent → Google Gemini LLM They never meet. In this PoC the ServiceNow-stored API Key is a placeholder — the ADK server does not validate it. The Gemini key is the only one that matters at runtime. In production, the external-agent API Key would be the real value issued by the external provider.
Discovery vs execution: This alias is execution-only. Agent Card discovery is handled by the platform Flow External AI Agent Card - A2A Protocol on the Provider record. No alias is needed for public /.well-known/ endpoints.
4e. Configure channels and activate
| Field | Value |
|---|---|
| Engage via Virtual Agent assistants | ON |
| Chat assistants | Now Assist in Virtual Agent |
| AI agent status | Active |
Click Save and test.
5. Test in the Playground
AI Agent Studio > Testing > Manual Test > Start Manual Test
- Test type — AI Agent or workflow
- Agent —
it_policy_advisor - Task — "What is the recommended password policy for enterprise systems?"
- Click Continue to test chat response
6. Verify execution
Open the latest record in sn_aia_execution_plan.list. Expect State = Completed with two execution tasks — Access verification and it_policy_advisor — both showing Status = Success.
Validated end-to-end
Tested on a sandbox instance (Zurich Patch 7) with the it_policy_advisor external agent. Result: PASS across all success criteria.
| Criterion | Result |
|---|---|
Agent Card discovery (/.well-known/agent-card.json) |
it_policy_advisor v0.0.1, Active |
Access verification (isAccessAllowed: true) |
Completed |
A2A invocation via message/send |
Completed — strategy AIA-External Agent Executor |
| Synchronous response latency | ~18 seconds end-to-end |
| Response rendering | Markdown policy recommendations rendered in Testing Playground |
| Execution plan state | Completed, both tasks Success |
| Bidirectional A2A (combined with Server PoC) | Proven |
Test prompt: "What is the recommended password policy for enterprise systems?"
Agent response: Gemini 2.5 Flash returned a complete 6-point policy (length, complexity, history, expiration, lockout, MFA).
Troubleshooting
| Problem | Fix |
|---|---|
| "No agents found" on Discover | Agent Card URL must include /.well-known/agent-card.json — not just the base URL |
| Discovery succeeds, execution returns nothing | Agent Card url points to localhost — restart ADK with the ngrok URL in to_a2a() |
| 429 RESOURCE_EXHAUSTED | Gemini free-tier quota exhausted. Switch to gemini-2.5-flash or regenerate the key |
| Agent invocation silently cancels | Communication mode is Async without a registered callback URL. Switch to Synchronous |
| ngrok URL changed after restart | Update agent.py, restart uvicorn, edit the Provider record, re-discover |
Resources
| Resource | Where |
|---|---|
| A2A Protocol spec (v1.0, LF-governed) | a2a-protocol.org |
| A2A GitHub repo | github.com/a2aproject/A2A |
| Google ADK A2A quickstart | adk.dev/a2a/quickstart-exposing |
| ServiceNow A2A FAQ | Enable MCP and A2A for agentic workflows |
| Companion article — Server PoC | Expose ServiceNow AI Agents via Google A2A |
Three takeaways
- ServiceNow speaks A2A in both directions — Server PoC validated inbound, this PoC validated outbound on Zurich Patch 7. Full bidirectional interoperability over an open, vendor-neutral protocol.
- No custom code on the ServiceNow side. Provider creation, Agent Card discovery, runtime invocation, and execution logging are all OOTB in AI Agent Fabric.
- Two credentials, two purposes. A platform Flow fetches the Agent Card (discovery), a Connection & Credential Alias on the agent record carries runtime auth (execution). Never confuse them.
Fastest path to try this yourself: Clone the A2A quickstart, run uvicorn agent:a2a_app --port 8001, tunnel with ngrok http 8001, and point a ServiceNow External Agent Provider at the public /.well-known/agent-card.json URL.
