Skip to main content

OpenAI Agents SDK adapter

Core history and delivery live in trytilde. This package converts typed context to OpenAI Agents SDK input items and channel tools to FunctionTools, bundles each invocation's run options (tilde_openai_agents) and lets tilde deploy discover module-level agents.

import tilde
from agents import Agent, OpenAIResponsesModel, Runner, set_tracing_disabled
from openai import AsyncOpenAI
from tilde_openai_agents import convert_to_openai_agents_messages, tilde_openai_agents

set_tracing_disabled(True)  # or OPENAI_AGENTS_DISABLE_TRACING=1; keeps traces out of OpenAI
INFERENCE = tilde.inference("default")
client = AsyncOpenAI(
    base_url=INFERENCE.base_url, api_key=INFERENCE.api_key, http_client=INFERENCE.async_client()
)
agent = Agent(
    name="assistant",
    instructions="Respond using the current channel's tools. Returned model text is private.",
    model=OpenAIResponsesModel(model="gpt-4o-mini", openai_client=client),
)


async def run(ctx):
    history = await ctx.message.history()
    items = await convert_to_openai_agents_messages(history.items, context=ctx)
    run_agent, run_config = await tilde_openai_agents(ctx, agent)
    await Runner.run(run_agent, items, run_config=run_config, max_turns=8)

tilde_openai_agents(ctx, agent, run_config=None) returns a clone of agent and a RunConfig (a copy of yours, when given):

  • the clone has the current channel's tools;
  • skills assigned in the registry: with a local ShellTool they join its environment skills (written to disk by ctx.skills.directory()); otherwise the clone gets the list_skills / read_skill tools and ctx.skills.summary() after its instructions;
  • the config's call_model_input_filter (chained after yours) checks cancellation before every model call, stamps the invocation's inference calls with the calling agent's dynamic instructions and adds steering input as user messages. The SDK sends filtered input for one call only, so steered messages are re-inserted where they arrived on later calls; with server-managed conversations (previous_response_id, conversation_id) that duplicates them.

Handoff targets and agent tools run as defined; only the returned agent has channel tools.

Deploy discovery

tilde deploy (entry point tilde.discover) registers every module-level Agent and the agents reachable through its handoffs and as_tool tools (cycles are fine): <name>/instructions (a string is plain, a function dynamic with its source) and <name>/handoff_description. Skill folders the SDK loads from disk are shipped: local ShellTool environment skills and a SandboxAgent's Skills(from_=LocalDir(...)) or lazy_from=LocalDirLazySkillSource(...), resolved from the working directory. Hosted prompts (prompt={"id": ...}) are versioned by OpenAI and reported as warnings. Handoff targets and agent-tool agents are read from private fields (openai-agents 0.22); an unreadable one is reported.

History pages are chronological; pass before_message_id=history.next_page_token for older messages. The latest page includes the current objective unless it already matches the latest received message. include_objective=False omits it. include_work=True also reads current goals/tasks and requires work.read. Only the acting agent's messages receive the assistant role (output_text parts); everything else is a user item (input_text).

Returned items never carry an id: the Responses API rejects ids it did not issue. The Tilde message id is stored only inside the cached representation, where it validates that a cached rendering belongs to the message being hydrated.

Images and PDFs are downloaded through ctx.attachments.download and embedded as input_image / input_file data URLs. Text files include their real content. Unsupported binary formats get an explicit attachment description; use on_attachment to parse them yourself. No private URL or credential needs to be exposed to the model. Without a context or custom handler, a message with attachments raises instead of being silently truncated.

history = await ctx.message.history(include_work=True)
items = await convert_to_openai_agents_messages(
    history.items,
    context=ctx,
    on_message=MessageHandlers(
        goal=lambda item: {
            "role": "user",
            "content": [{"type": "input_text", "text": f"Our goal: {item.goal.objective}"}],
        },
        task=lambda item: None,  # Omit this type, or provide a different rendering.
    ),
    on_attachment=decode_your_format,  # async def (AttachmentConversion) -> part | [parts] | None
)

MessageHandlers supports message, objective, goal, and task; handlers may be sync or async. Supplied handlers take precedence over cached/default rendering; returning None omits an item. Without an override the converter renders all supported types (incomplete conversation messages are skipped unless a message handler is given). Completed conversation conversions use the existing per-agent cache, in bounded batches (100 items or 1 MiB). Files are hydrated afresh and are never stored as data URLs in the cache; objectives/goals/tasks remain live projections rather than cached chat records.

Channel tools

convert_to_openai_agents_tools(ctx.channel.current) preserves the provider's descriptions and JSON schemas (strict_json_schema=False, so provider schemas are used unchanged) and forwards the Agents SDK tool-call id (ToolContext.tool_call_id) to Tilde's audited tool execution. Provider results are returned to the model as JSON strings. The adapter does not publish the model's final text. The agent chooses the provider tool and arguments, including routing fields required by that provider.

Override tool instructions with instructions={"sendMessage": "..."}, or change the channel tool's description before conversion. When combining collections, use prefix="slack_" (or another prefix) to keep model tool names distinct; names are sanitized to [a-zA-Z0-9_-], truncated to 64 characters with a stable hash suffix, and conflicts raise.

The core SDK exposes callable tools on ctx.channel.slack, github, agentmail, linq, whatsapp, telnyx_whatsapp, and native. Use ctx.channel.connections() and ctx.channel.for_connection(id) when multiple connections use a provider. ctx.channel.current never falls back to a different connection.

Bundled tools

The agent's own function tools join Tilde's with one call:

from agents import Agent, function_tool
from tilde import BundledOptions
from tilde_openai_agents import with_tilde_tools


@function_tool
def roll_dice(count: int = 1) -> list[int]:
    """Roll six-sided dice."""
    return [random.randint(1, 6) for _ in range(count)]


tools = await with_tilde_tools(
    ctx, [roll_dice], options={"roll_dice": BundledOptions(summary="Rolled dice")}
)
agent = Agent(name="assistant", tools=tools)

with_tilde_tools returns the current channel's tools, ctx.agent_tools and copies of the native FunctionTools with an audited on_invoke_tool, and publishes the native tools to Tilde with their parameter and output schemas, so tools.search finds them and a tools.execute naming one runs it here with the run's context. Every call is audited once with the model's call id. FunctionTool has no free metadata, so summaries come from options. @function_tool turns an exception into an error string for the model by default, so such a failure is audited as completed with that text; failure_error_function=None audits it as failed (and fails the run).

Metadata

Release files for trytilde-openai-agents 3.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 trytilde-openai-agents 3.1.0
File Size Uploaded
trytilde_openai_agents-3.1.0.tar.gz 13.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for trytilde-openai-agents 3.1.0
File Interpreter ABI Platform
trytilde_openai_agents-3.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 29.4 kB

Release files / trytilde_openai_agents-3.1.0.tar.gz

Download URL trytilde_openai_agents-3.1.0.tar.gz
Size 13.0 kB
Tags Source
SHA-256 checksum
How to use checksums
d6e489f96b60a6168b6ee81186e0c7263063c8ce26be331d1095d2df18d670fa
BLAKE2b-256 checksum
How to use checksums
c482f879c10bd6b1a34e429f4588156c951d199ba5f8f20c0606645cfcc2e449
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / trytilde_openai_agents-3.1.0-py3-none-any.whl

Download URL trytilde_openai_agents-3.1.0-py3-none-any.whl
Size 16.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
94d498adc98f5f46f797ed53b7120ac3648c2669a10579ceef0c819a7f37cdc0
BLAKE2b-256 checksum
How to use checksums
5f24a50318386fcfc19bffc2f43ee4c7ae540f1263abc6cd799fb0ee9871e6ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

3.1.0 This release

2 release files

3.0.1

2 release files

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