Agents SDK blocked_tool_names: hide Sume paid tools from a model
create_static_tool_filter takes allowed and blocked tool names. Use it so an agent on Sume's hosted MCP can read, but never sees a paid generate tool.

Filter at the server object. In the OpenAI Agents SDK for Python, MCPServerStreamableHttp accepts a tool_filter, and create_static_tool_filter builds one from allowed_tool_names and blocked_tool_names (read 2026-10-05). A model that never sees generate_video cannot call it, whatever the prompt says.
Allow list first, block list second
The SDK page describes two filter styles: a static filter with allow and block lists, and a dynamic callable that receives a ToolFilterContext and returns a boolean per tool (read 2026-10-05). For Sume, an allow list is safer. Sume's tool inventory changes, and a block list only hides names you remembered to write down.
Sume's docs split the hosted tools into read tools and paid tools. Discovery and reads, such as tools_list, balance_get, catalog_list, jobs_status and jobs_result, spend nothing. Paid tools include generate_image, generate_video, music_create and tts_create.
| Approach | How | Risk |
|---|---|---|
| Allow list | allowed_tool_names=[read tools] | New Sume tools stay hidden until you add them |
| Block list | blocked_tool_names=[paid tools] | A newly added paid tool is visible by default |
| Dynamic filter | Callable on ToolFilterContext | More code to test |
| OAuth mcp:read session | Server hides write and paid tools | Not a filter, but a second layer |
A read-only Sume agent
This agent can discover tools, check the balance and read jobs. The key comes from the environment, and the script exits if it is missing. It needs the openai-agents package and network access.
import asyncio, os
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp, create_static_tool_filter
READ_ONLY = ["tools_list", "mcp_health", "balance_get",
"catalog_list", "jobs_status", "jobs_result"]
async def main() -> None:
key = os.environ["SUME_API_KEY"]
async with MCPServerStreamableHttp(
name="sume",
params={"url": "https://mcp.sume.com/mcp",
"headers": {"Authorization": f"Bearer {key}"}},
tool_filter=create_static_tool_filter(
allowed_tool_names=READ_ONLY),
) as server:
agent = Agent(name="Auditor", mcp_servers=[server],
instructions="Report the balance. Do not generate.")
result = await Runner.run(agent, "What is my balance?")
print(result.final_output)
asyncio.run(main())Why a filter and not just a prompt
An instruction such as do not generate anything is advice. A filter is enforcement. If injected text in a scraped page tells the model to start a render, the tool is not in its list, so the call cannot be formed.
Keep a second layer. Sume paid calls still need idempotency_key, and max_spend_usd is enforced only when you provide it, so give agents that may spend an explicit cap.
Approvals still apply to what remains
Filtering decides what the model can see. Approval decides what it may run. The SDK page describes require_approval as always, never, a boolean, or a per-tool mapping, and the two features combine: expose a small set of tools, then require approval on any that change data (read 2026-10-05).
If you later add a paid tool to the allow list, add it to the approval mapping in the same change, so there is no window in which it is visible and unapproved.
Test the filter
Check the list the model sees, not the one you intended.
- List the server's tools after the filter and assert no paid name appears.
- Run the agent against a read-only OAuth session as well, to confirm both layers agree.
- Re-review the allow list whenever Sume adds a tool to its inventory.
Sources
Related posts
More in Developers
- OpenAI gave 184 days to leave the Videos API: a CI catalog check
Notice March 24, removal September 24, 2026, no replacement listed. An 18-line Python check fails CI when a video model id or duration leaves Sume's catalog.
- OpenRouter puts an idempotency key on video webhooks; Sume uses job_id
OpenRouter's video guide adds an idempotency key header to each delivery. Sume dedupes on job_id and takes Idempotency-Key on submit. Which key goes where.
- OpenRouter video callbacks vs Sume job webhooks: what differs
OpenRouter video callback_url reports completed, failed, cancelled, expired. Sume job webhooks send completed, failed, canceled, signed with HMAC-SHA256.
- Submit 60 Gemini Omni 4K jobs on a Pro plan: pace in waves of 24
A Pro workspace holds 24 accepted generation jobs (4 running, 20 queued). Pace 60 Omni 4K submits in waves with asyncio and retry queue_full safely.
Written by Sume