SAP Ships the Boring Half of Agents: a Gateway, a Registry, and a Rule That Unverified Agents Cannot Be Called
💡 Tool Tip: cURL Command Generator, API Tester, JWT Decoder
SAP's TechEd keynote on October 28 spent very little time on model quality and a great deal of time on the parts nobody demos: a gateway, a registry, a verification gate, an audit trail. That is the right instinct, and it is worth reading closely even if you never touch SAP. The headline claims are that Joule Studio takes an agent from stated intent to working in about 2.5 hours instead of 13, at roughly 50% lower cost per task because agents no longer guess at requests and use fewer tokens; that there are 40 assistants and 300 agents shipping between SAP and its partners; and that agents not verified in SAP AI Agent Hub cannot be invoked at runtime. Two of those are marketing. The third is an architectural decision worth stealing this quarter.
Agent gateway is generally available today; the Enterprise AI Gateway sits above it.
1. The numbers, and what they are actually measuring
Forty assistants and three hundred agents is a catalogue count, and SAP is explicit that these are split between SAP and its partners. Every one of them is described as ISO and SOC compliant, which is a claim about the controls around the workload rather than about the agent's competence. The time-to-agent figure is more interesting: 2.5 hours versus 13, with 50% lower cost per task, caused by agents using fewer tokens because a Process Consulting Agent identifies what to build, the SAP Knowledge Graph locates the relevant APIs, MCP servers and data products, and Joule Studio generates the specification, structure and integration logic. Read that as a claim about removal of ambiguity, not about model speed. Most of the 13 hours was never compute. It was figuring out which endpoint to call.
# The registry record. Everything else in this pattern reads from here.
# Keep it boring and keep it in a database, not in a spreadsheet.
import sqlite3
SCHEMA = """
CREATE TABLE IF NOT EXISTS agents (
agent_id TEXT PRIMARY KEY,
owner TEXT NOT NULL,
version TEXT NOT NULL,
capabilities TEXT NOT NULL, -- JSON array of declared capability names
scopes TEXT NOT NULL, -- JSON array of granted scopes
endpoint TEXT NOT NULL,
verified_at TEXT, -- ISO 8601, NULL means never verified
verified_by TEXT,
expires_at TEXT -- verification is not permanent
);
CREATE TABLE IF NOT EXISTS invocations (
trace_id TEXT PRIMARY KEY,
agent_id TEXT NOT NULL,
version TEXT NOT NULL,
caller TEXT NOT NULL,
scopes_used TEXT NOT NULL,
outcome TEXT NOT NULL,
started_at TEXT NOT NULL,
FOREIGN KEY (agent_id) REFERENCES agents(agent_id)
);
"""
def init(path="agents.db"):
con = sqlite3.connect(path)
con.executescript(SCHEMA)
con.commit()
return con
# Note the two tables together. The registry alone is a spreadsheet with
# extra steps. The registry plus the invocation log is an audit trail, and
# the audit trail is what a risk classification is built from later.2. A gateway is generally available, and a bigger one sits above it
SAP says its agent gateway is generally available today and connects agents and endpoints across any landscape boundary. For scenarios needing rate limiting, routing, protocol translation and advanced access control, it announced SAP Enterprise AI Gateway, built on SAP Integration Suite as an overlay rather than a replacement. Two things are worth noting about that shape. First, the gateway is positioned as the thing that stops every new platform from requiring a bespoke integration, which is the actual cost driver in a landscape with dozens of data sources. Second, SAP states every agent it ships is natively an A2A endpoint. That is the same posture as the Agent2Agent specification: the agent's contract is a published card, not a private SDK, so the gateway can route on capability rather than on vendor. If you are building internal agents, publishing a card and putting a gateway in front is the cheapest portability insurance you can buy.
# Serve the record as an agent card so a gateway can route on capability
# rather than on vendor. This is the A2A-style contract SAP describes.
import json
import sqlite3
def agent_card(con, agent_id: str) -> dict:
row = con.execute(
"SELECT agent_id, owner, version, capabilities, scopes, endpoint,"
" verified_at, expires_at FROM agents WHERE agent_id = ?",
(agent_id,),
).fetchone()
if row is None:
raise KeyError(agent_id)
return {
"agent_id": row[0],
"owner": row[1],
"version": row[2],
"capabilities": json.loads(row[3]),
"scopes": json.loads(row[4]),
"endpoint": row[5],
"verification": {
"verified_at": row[6],
"expires_at": row[7],
"status": "verified" if row[6] else "unverified",
},
# A card that does not say how to call it is documentation, not a contract.
"protocol": "a2a/1.0",
"content_types": ["application/json"],
}
# Publish at /.well-known/agent/{agent_id} or whatever your gateway reads.
# The point is that the gateway never needs a bespoke integration: it reads
# the card, matches the capability the caller asked for, and routes.3. Runtime verification enforcement is the real announcement
The sentence to underline: runtime verification enforcement ensures that agents not verified in SAP AI Agent Hub cannot be invoked. That is not a policy document. That is a gate in the call path, and it inverts the usual enterprise pattern where governance is a review that happens before launch and then stops mattering. It also gives the governance story a mechanism. Michelle Niedernhuber, lead product manager for SAP AI Agent Hub, put the design goal precisely: you need to connect the design-time layer where an agent is defined, assessed and verified with the runtime layer that enforces, monitors and optimises behaviour. Her line about the whole exercise is worth quoting because it is the opposite of how governance is usually sold: governance is not what slows AI adoption, it is what makes adoption at scale possible. Whether that survives contact with a real change board is another question, but the mechanism is sound.
# The gate. This is the whole announcement: unverified means uninvocable,
# enforced in the call path rather than in a review document.
from datetime import datetime, timezone
class UnverifiedAgent(Exception):
pass
def call_agent(con, agent_id: str, caller: str, scope: str, payload: dict, dispatch):
row = con.execute(
"SELECT version, scopes, verified_at, expires_at FROM agents WHERE agent_id = ?",
(agent_id,),
).fetchone()
if row is None:
raise UnverifiedAgent(f"{agent_id}: not in registry")
version, scopes, verified_at, expires_at = row
if not verified_at:
raise UnverifiedAgent(f"{agent_id}: never verified")
now = datetime.now(timezone.utc)
if expires_at and datetime.fromisoformat(expires_at) <= now:
raise UnverifiedAgent(f"{agent_id}: verification expired at {expires_at}")
if scope not in scopes_json(scopes):
raise PermissionError(f"{agent_id}: scope {scope!r} not granted")
trace_id = new_trace_id()
try:
result = dispatch(payload)
except Exception as exc:
log(con, trace_id, agent_id, version, caller, scope, "error")
raise
log(con, trace_id, agent_id, version, caller, scope, "ok")
return {"trace_id": trace_id, "result": result}
# Two details that decide whether this survives a real incident review:
# 1. Verification has an expiry. A verification from eighteen months ago
# is a historical fact, not a current guarantee.
# 2. The trace_id is returned to the caller. Without it, the log exists but
# nobody can join it to the request that went wrong.4. Where the EU AI Act shows up in a product roadmap
With the EU AI Act in force, SAP says it will release an AI Governance Assistant to Early Adopter Care customers in November. The described behaviour is specific and unglamorous: it uses information the customer already has, walks the agent owner through the remaining questions, and produces an audit-ready AI risk classification. That is the correct division of labour. Classification is a form to fill in, and a model is good at forms; the facts that determine the classification are organisational and only the owner has them. The same section mentions agent observability and SAP Signavio agent mining closing the loop between agent design and production behaviour. If you are shipping agents into the EU, the practical work item is to make sure the evidence the assistant would ask for already exists in machine-readable form, because retrofitting a risk classification onto a system with no invocation logs is a quarter of work.
# Rate limiting and budget at the gateway, not in the agent. An agent that
# polices its own spending is an agent that can be talked out of it.
import time
from collections import defaultdict, deque
class TokenBucket:
def __init__(self, per_minute: int):
self.capacity = per_minute
self.tokens = float(per_minute)
self.rate = per_minute / 60.0
self.updated = time.monotonic()
def take(self, n: float = 1.0) -> bool:
now = time.monotonic()
self.tokens = min(self.capacity, self.tokens + (now - self.updated) * self.rate)
self.updated = now
if self.tokens < n:
return False
self.tokens -= n
return True
LIMITS = defaultdict(lambda: TokenBucket(60)) # per agent_id
DAILY_TOKEN_BUDGET = defaultdict(int)
def admit(agent_id: str, estimated_tokens: int) -> tuple[bool, str]:
if not LIMITS[agent_id].take():
return False, "rate limited"
if DAILY_TOKEN_BUDGET[agent_id] + estimated_tokens > 2_000_000:
return False, "daily token budget exhausted"
DAILY_TOKEN_BUDGET[agent_id] += estimated_tokens
return True, "admitted"
# Why here and not in the agent: the agent's context can be influenced by the
# content it processes. The gateway's cannot. Put every number that must not
# be negotiable outside the thing that can be persuaded.5. The skill abstraction is a bet on non-developers, and it has a cost
Joule Studio's headline abstraction is the skill: a natural language description plus a few lines of code defining what an agent should do, which SAP describes as opening agent-building beyond developers. Joule Work, the redesigned front end, has been tested by more than 110,000 SAP employees plus more than 150 customers in the Early Adopter Care programme, and connects SAP applications alongside Office365, Claude Cowork, Glean and ServiceNow out of the box. There is a real argument for this: the people who know what a process should do are rarely the people who can write the integration, and moving the definition closer to the domain expert removes a translation step that has historically been the main source of rework. The cost is that natural language descriptions are not testable the way code is. If you adopt this pattern, the skill description needs an acceptance test attached to it, or the abstraction just moves the ambiguity somewhere less visible.
# Protocol translation at the gateway: expose one internal contract and
# translate to whatever the endpoint actually speaks. This is what stops a
# bespoke integration per platform from accumulating.
import json
def to_openai_chat(request: dict) -> dict:
return {
"model": request["model"],
"messages": [{"role": m["role"], "content": m["text"]} for m in request["messages"]],
"max_tokens": request.get("max_output_tokens", 4096),
"temperature": request.get("temperature", 1.0),
}
def to_mcp_tool_call(request: dict) -> dict:
return {
"jsonrpc": "2.0",
"id": request["trace_id"],
"method": "tools/call",
"params": {"name": request["capability"], "arguments": request["arguments"]},
}
def to_a2a_task(request: dict) -> dict:
return {
"task": {
"id": request["trace_id"],
"message": {"role": "user", "parts": [{"text": request["prompt"]}]},
}
}
ADAPTERS = {
"openai-chat": to_openai_chat,
"mcp": to_mcp_tool_call,
"a2a": to_a2a_task,
}
def translate(request: dict) -> dict:
target = request["protocol"]
if target not in ADAPTERS:
raise ValueError(f"unsupported protocol: {target}")
return ADAPTERS[target](request)
# Keep the internal contract narrow on purpose. Every field you allow into it
# is a field every adapter must handle, forever.6. Copying the pattern without buying the platform
The three pieces are separable and each is small. A registry: a table with agent id, owner, version, declared capabilities, scopes, verification status and verification timestamp. A card endpoint: serve that record as JSON at a well-known path so a gateway can route on it. A gate: one function in the call path that reads the registry and refuses anything without a fresh verification. Add an invocation log with trace id, agent id, version, caller, scopes used and outcome — that log is what makes the risk classification and the audit trail possible later. None of this needs a vendor. It needs two engineers and a decision that unverified means uninvocable, enforced in code rather than in a wiki. That last part is the whole announcement.
Runtime verification enforcement: no verification record, no invocation.
Design-time oversight and runtime enforcement, connected by one registry.
📌 Frequently Asked Questions
Is SAP's agent gateway generally available?
Yes. SAP said at TechEd 2026 that its agent gateway is generally available as of October 28, 2026, connecting agents and endpoints across landscape boundaries. SAP Enterprise AI Gateway, built on SAP Integration Suite, is announced as the overlay for rate limiting, routing, protocol translation and advanced access control.
What does runtime verification enforcement actually do?
It blocks invocation. Agents that have not been verified in SAP AI Agent Hub cannot be called at runtime, which moves governance from a pre-launch review document into a gate in the call path.
How many agents and assistants did SAP announce?
Forty assistants and three hundred agents, split between SAP and its partners. SAP describes each of them as ISO and SOC compliant and says each is natively an A2A endpoint connected through its A2A gateway.
Where does the 2.5-hours-versus-13-hours number come from?
SAP attributes it to Joule Studio plus the Process Consulting Agent and SAP Knowledge Graph, which identify what to build and locate the relevant APIs, MCP servers and data products before any agent is generated. The stated effect is roughly 50% lower cost per task because agents use fewer tokens when the request is unambiguous.
Can the SAP governance pattern be replicated without SAP?
Yes, and cheaply: an agent registry table, a card endpoint serving registry records as JSON, a verification gate in the call path that refuses unverified agents, and an invocation log carrying trace id, version, scopes and outcome. The governance value comes from the gate being enforced in code.
🔧 Recommended Tools
📚 Sources
- SAP News Center — SAP TechEd 2026: Developers Can Build the Autonomous Enterprise (Oct 28, 2026)
- BigDATAwire — SAP expands AI agent development, data integration and governance tools (Oct 29, 2026)
- A2A Protocol — Agent2Agent specification (the endpoint model SAP says every agent exposes natively)
- EU AI Act — implementation timeline (the regulation the new Governance Assistant classifies against)