Skip to main content

openai-agents-submilli

Submilli is a dedicated secure runtime for code-mode agents, with built-in isolation, governance, and permissions.

openai-agents-submilli is the Python integration for the OpenAI Agents SDK. It lets your agent execute TypeScript code in Submilli's runtime, and lets that code call your existing function tools under the Blueprint's policy and the SDK's own approvals.

Install

Python 3.11 or later and submilli-server 0.4.1 or later are required.

pip install openai-agents-submilli

Follow Connect OpenAI Agents for a complete setup with a server, Blueprint, model provider, agent, and session cleanup.

Use it

from agents import Agent, Runner
from openai_agents_submilli import SubmilliTools

# Server and token come from SUBMILLI_SERVER and SUBMILLI_SERVER_TOKEN.
submilli = SubmilliTools(blueprint="research")

# Built once and shared: the user and the conversation come with each run.
agent = Agent(name="researcher", instructions="...", tools=submilli.tools)

result = await Runner.run(
    agent,
    "What is new in the latest Rust release?",
    context={"user_id": "u_ada", "conversation_id": "c_1"},
)

# When the conversation is over:
await submilli.aclose_conversation("c_1")

Toolkit reference

The tools are async. Runner.run, Runner.run_streamed, and Runner.run_sync all work.

SubmilliTools(
    blueprint="research",
    server=None,
    token=None,
    variables=None,
    secrets=None,
    conversation_id=None,
    store=None,
    client=None,
    ptc=None,
)
Setting Contract
blueprint Name of a Blueprint already registered on the server; used for every program
server submilli-server URL; defaults to $SUBMILLI_SERVER, then http://127.0.0.1:8128
token Server token; defaults to $SUBMILLI_SERVER_TOKEN
variables Fixed dict[str, str], or a function from the run context to one; defaults to mapping context user_id to Blueprint variable userId
secrets Fixed dict[str, str], or a function from the run context to one, for the Blueprint's harness secrets
conversation_id Function from the run context to the conversation's id; defaults to reading context conversation_id
store Where each conversation's session id is kept: InMemorySessionStore (default), SQLiteSessionStore, or your own SessionStore
client Existing submilli.AsyncSubmilli; replaces server and token
ptc Application tools that programs may call through the @tools Package

The run context is the context you pass to Runner.run. It may be a dict, a dataclass, or a Pydantic model; the defaults read user_id and conversation_id as keys or attributes. The model never sees it.

submilli.tools holds the six tools below. Before the first model call, the toolkit fetches the instructions for using them from the Submilli server.

Tool Does
submilli__typescript__execute Runs a program
submilli__typescript__last_run Returns the conversation's last run and full console
submilli__typescript__packages__search Searches Packages available to the program
submilli__typescript__packages__docs Returns a Package's documentation and declarations
submilli__typescript__builtins__list Lists built-ins available without an import
submilli__typescript__builtins__docs Returns declarations for selected built-ins

Sessions, retries, and results

  • The first program in a conversation opens a Submilli session, and later turns of the same conversation reuse it. The session id is kept in the store. The default store lives in memory; to reuse sessions after your application restarts, or from another worker, use SQLiteSessionStore("conversations.db") (it can share a file with the SDK's SQLiteSession) or implement SessionStore over your own database. Close the session with await submilli.aclose_conversation(conversation_id).
  • Blueprint variables are fixed when the session opens. A later run in the same conversation with different values raises SubmilliSessionMismatchError before the model is called.
  • Harness secrets are sent when a session opens and are never stored. End the session before using rotated secrets.
  • Each execute call sends an Idempotency-Key derived from the SDK's tool call id. A repeated call replays the recorded result. The toolkit reports conflicts and incomplete, in-progress, or unavailable replays without silently rerunning the program.
  • When a session has ended, the toolkit opens a replacement and tells the model. If a restarted server asks for the session's secrets, it rebinds them once and retries.
  • On a server with durable execution, the toolkit waits for a queued run. A run that stops without a result, such as one that is stuck or cancelled, comes back to the model as an error with the run's status and reason.
  • The execute output the model reads contains result, console, error, denied, and the program's application-tool calls (tool_calls: tool, arguments, outcome), so that after a refusal the model can say which calls already took effect. The output item's custom_data, which the model never sees, contains execution_id, session_id, and the same calls with their call_ids, for linking to the audit trail.
  • Errors that are the application's raise: a bad token, an unknown Blueprint, invalid variables, a missing conversation id, an unreachable server. Errors found while a tool runs reach you as the cause of the SDK's UserError. Program failures and denials are tool results.

Submilli enforces the Blueprint only for code that runs through Submilli. Other tools you give the agent keep their own permission boundaries.

Application tools

Let programs reuse your existing function tools. A model-written program can combine calls, loop over results, branch on conditions, and process the results in one run.

from agents import function_tool


@function_tool
def lookup_order(order_id: str) -> Order: ...


@function_tool(needs_approval=True)
def refund(order_id: str, amount: float) -> str: ...


submilli = SubmilliTools(blueprint="support", ptc=[lookup_order, refund])
agent = Agent(name="support", tools=submilli.tools)

The ptc parameter (programmatic tool calling) tells the toolkit which tools programs can use. Submilli makes them available to the program through the @tools Package, so the program can import and call them. In your Blueprint, grant tools.call with a filter for each allowed tool name.

Each call runs as an ordinary tool call of the SDK, with the run's context, the tool's guardrails, timeout, and tracing. Input types come from the tool's schema, and return types come from its output_json_schema or return annotation. Use a TypedDict (from typing_extensions before Python 3.12) or a Pydantic model for typed objects. A raised exception becomes an Error in the TypeScript program.

Tools in ptc are not given to the model directly. If you also pass them to the agent, direct model calls bypass Submilli's Blueprint checks.

A session keeps the application-tool catalog it opened with. Changing the catalog causes the conversation's next call to open a new session.

Approvals

A tool with needs_approval pauses the program at each call that needs approval, the same way the SDK pauses at a direct tool call. The run result's interruptions holds a ToolApprovalItem for your tool, with the program's arguments. Approve or reject it on the run state and run again:

result = await Runner.run(agent, "Refund order o_7", context=context)
while result.interruptions:
    state = result.to_state()
    for item in result.interruptions:
        if ask_a_person(item.tool_name, item.arguments):
            state.approve(item)
        else:
            state.reject(item, rejection_message="Refunds over $25 need a manager.")
    result = await Runner.run(agent, state)

The program waits on the server meanwhile, up to the Blueprint's tool_call_timeout. A rejection throws PermissionDeniedError in the program with your message. Each call that needs approval pauses on its own, so a program that refunds three orders asks three times. The state can be saved with to_string() and resumed with RunState.from_string in another process. The program finishes in the session it started in; share the store too so that later turns of the conversation keep using that session.

A run left waiting is not an answer. To go on without one, reject the pending calls on the state and run it, which lets the program finish, or drop the unanswered call from the input you pass to the next run: the Responses API refuses an input that holds a tool call without its output. A dropped program keeps waiting on the server until tool_call_timeout, and its call never runs.

Submilli documentation

Development

This package lives in the submilli-python workspace. See the repository README for workspace setup, checks, and releases.

uv run pytest                          # unit tests; the HTTP API is mocked
uv run pytest tests/integration_tests  # starts a server from $SUBMILLI_BIN or PATH

The integration tests use a scripted model and need no model provider key.

Implementation notes are in NOTES.md.

License

Apache-2.0.

Metadata

Release files for openai-agents-submilli 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for openai-agents-submilli 0.1.0
File Size Uploaded Provenance Actions
openai_agents_submilli-0.1.0.tar.gz 42.6 kB With provenance Details for openai_agents_submilli-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for openai-agents-submilli 0.1.0
File Interpreter ABI Platform Actions
openai_agents_submilli-0.1.0-py3-none-any.whl Python 3 none any Details for openai_agents_submilli-0.1.0-py3-none-any.whl

Total release size: 70.9 kB

Release files / openai_agents_submilli-0.1.0.tar.gz

Download URL openai_agents_submilli-0.1.0.tar.gz
Size 42.6 kB
Tags Source
SHA-256 checksum
How to use checksums
3aabe01adf695f945e29f9bc05fdffbeab28f1d8e3b8fa0859a875697dee6f82
BLAKE2b-256 checksum
How to use checksums
19c17ac27c11f5c6d5714bd561186206dc9b478a8f8e4478ca4cb29cb7992e04
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.

Transparency log

Release files / openai_agents_submilli-0.1.0-py3-none-any.whl

Download URL openai_agents_submilli-0.1.0-py3-none-any.whl
Size 28.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
09397bf13d55984da86f8ab46c4b49b9df9ac02ae8604dcac8ac9cfdd691b778
BLAKE2b-256 checksum
How to use checksums
79d39b722b024d119541808cb354137e342ad175fbf6be85ac0256bb25cc5415
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.

Transparency log

Security for openai-agents-submilli 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for openai_agents_submilli-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page