OpenAI Agents
How do I connect an OpenAI Agents SDK agent to Inhold?
Inhold connects to an OpenAI Agents SDK agent through one MCP server entry with a token and a purpose header. Refusals come back as ordinary tool errors.
Inhold is being built. No customers yet. Repo goes public 9 Nov 2026.
The part you copy
One MCP server entry
Everything else in the example file is the demo.
headers = {"Authorization": "Bearer <token>", "Inhold-Purpose": "billing"}
MCPServerStreamableHttp(name="inhold", params={"url": url, "headers": headers})Start a local gateway
From the repo root, with Inhold installed. It makes a fresh database, seeds one billing note and one clinical note, and serves MCP at http://127.0.0.1:8700/mcp.
python examples/gateway.py
Run the OpenAI Agents SDK example
In a second terminal. Each SDK gets its own virtualenv because their MCP client versions disagree.
python -m venv .venv-openai && .venv-openai/bin/pip install -r examples/requirements-openai.txt .venv-openai/bin/python examples/with_openai_agents.py --no-model
Read the output
The billing agent gets the billing note and a refusal for the clinical one. Then the script reads the log the way the hospital's security team would.
context_get ctx_a4fc2fea0a10 -> Payer Northwind rejects claims without modifier 25; resubmit within 30 days. context_get ctx_1c79d9bf86eb -> REFUSED: Error executing tool context_get: not readable; do not retry audit rows written during this run: #5 billing-agent read ctx_a4fc2fea0a10 purpose=billing -> ALLOW (purpose 'billing' may read internal) #6 billing-agent read ctx_1c79d9bf86eb purpose=billing -> DENY (purpose 'billing' may not read items written under 'prior_auth')
This run used --no-model: the same two MCP calls through the SDK's own client, with no model in the loop. With a key, the model decides when to call the tools. Output from our run on main 478aded, 31 Oct 2026; ids differ on each run.
Worth knowing
Four things the example shows
The purpose is a header
It sits in your config. The model never sees it and no tool takes it as an argument, so a prompt injection cannot talk its way into another purpose.
A refusal is a normal tool error
The SDK hands it back to the model and the run carries on. The message is the same for a forbidden note and a missing one, so the agent cannot probe. The real reason is only in the audit row.
Hiding tools is your hygiene
The example offers the model only the read tools. The hospital's control is the policy on the gateway, which decides every call either way.
Sign-in in a real install
In AWS your agent signs each request with its IAM role instead of a bearer token. The OpenAI client takes an auth= object next to headers=, so every request gets a fresh signature; demo/integrate/remote_client.py shows the signing. Agent sign-in has been tested against a stand-in for STS, not yet a real AWS account.