inhold Book a call

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.

Last checked 31 Oct 2026, written by Vivek

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.