Tools¶
Runtime-proxied callables exposed to agents under policy.
from murmur.tools import (
StaticToolProvider,
ToolExecutor,
ToolFunc,
ToolRegistry,
mcp_http,
mcp_sse,
mcp_stdio,
)
from murmur.tools import (
AbstractBuiltinTool,
CodeExecutionTool,
FileSearchTool,
ImageGenerationTool,
MCPServerTool,
MemoryTool,
WebFetchTool,
WebSearchTool,
XSearchTool,
)
Registry¶
ToolRegistry¶
ToolRegistry
¶
In-memory map of tool name → callable. Not a pluggable; data store only.
Source code in src/murmur/tools/registry.py
register
¶
register(name: str, func: ToolFunc[T]) -> None
Register a tool under name, preserving its return type at the call site.
The method is generic over T so a caller passing ToolFunc[str]
keeps the typed view in their own code. The registry erases T to
Any on storage (see __init__); retrieval via :meth:get
returns ToolFunc[Any] because no caller can know the original
T at lookup time.
Source code in src/murmur/tools/registry.py
unregister
¶
Remove name from the registry. Idempotent — silent on miss.
Used for short-lived tool registrations (e.g. AgentTeam's
per-run delegate tool) where the registration scope is one
runtime.run_group(team, ...) call rather than the runtime's
lifetime.
Source code in src/murmur/tools/registry.py
StaticToolProvider¶
StaticToolProvider
¶
ToolFunc¶
ToolFunc
module-attribute
¶
Tool callable parameterised by its result type.
Use bare ToolFunc (or explicitly ToolFunc[Any]) when you don't care
about the result type — the registry stores tools heterogeneously and
returns ToolFunc[Any]. Use ToolFunc[MyType] in user code to keep the
return-type information visible to type checkers when the caller knows the
shape of the tool's output.
async def web_search(query: str) -> str: ... typed: ToolFunc[str] = web_search # ty narrows to
Awaitable[str]registry.register("web_search", typed) # registry erases T to Any
Executor¶
ToolExecutor¶
ToolExecutor
¶
ToolExecutor(registry: ToolRegistry, *, event_emitter: EventEmitter | None = None)
Policy-aware tool dispatcher.
Source code in src/murmur/tools/executor.py
registry
property
¶
registry: ToolRegistry
The :class:ToolRegistry this executor consults at execute time.
Exposed as a public read-only attribute so callers that pass a custom executor can pin runtime/backend registry identity against this value — keeping the registry visible at the agent- build path and at execution-time fall-through aligned.
execute
async
¶
execute(
*,
agent_name: str,
task_id: str,
trust_level: TrustLevel,
allowed: frozenset[str],
name: str,
args: dict[str, object],
trace_id: str | None = None,
external_call: Callable[..., Awaitable[object]] | None = None,
low_trust_overrides: frozenset[str] = frozenset(),
) -> object
Apply policy, emit lifecycle events, dispatch.
external_call is the escape hatch for tools that don't live in the
local :class:ToolRegistry — currently MCP-discovered tools, where the
callable closes over the originating provider plus the tool name. The
same trust + allow-list + lifecycle-event gate runs regardless of which
dispatch path the call takes.
low_trust_overrides is the per-call extension to
:data:_READ_ONLY_TOOLS. MCP providers pass their explicit allow
list here so a user who opts a tool into LOW trust at the provider
level isn't blocked by the global read-only set (which only knows
about native tools).
trace_id is forwarded into the emitted :class:RuntimeEvent. When
None (the default for unwired callers), task_id substitutes —
a tool call without a task lineage is rare but possible in tests.
Source code in src/murmur/tools/executor.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
MCP factories¶
Construct ToolsetProvider instances backed by the three MCP
transports. See the MCP concept page for trust
matrix, prefixing, and lifecycle modes.
mcp_stdio¶
mcp_stdio
¶
mcp_stdio(
command: str,
args: Sequence[str] = (),
*,
env: Mapping[str, str] | None = None,
cwd: str | Path | None = None,
allow: Sequence[str] | None = None,
prefix: str | None = None,
) -> MCPToolsetProvider
Build an :class:MCPToolsetProvider over a stdio MCP server subprocess.
The subprocess is spawned lazily on the first
:meth:MCPToolsetProvider.start call (the runtime owns lifecycle).
| PARAMETER | DESCRIPTION |
|---|---|
command
|
Executable to run (e.g.
TYPE:
|
args
|
Positional arguments passed to
TYPE:
|
env
|
Environment variables for the child process.
TYPE:
|
cwd
|
Working directory for the child process.
TYPE:
|
allow
|
Explicit tool allow-list. See
:class:
TYPE:
|
prefix
|
Optional namespace prefix prepended to every tool name the
server reports — e.g.
TYPE:
|
Source code in src/murmur/tools/mcp.py
mcp_http¶
mcp_http
¶
mcp_http(
url: str,
*,
headers: Mapping[str, str] | None = None,
allow: Sequence[str] | None = None,
prefix: str | None = None,
) -> MCPToolsetProvider
Build an :class:MCPToolsetProvider over a Streamable-HTTP MCP server.
Used for newer MCP servers that speak the streamable-HTTP transport.
Use :func:mcp_sse for legacy SSE-only servers. allow is the
optional tool allow-list — see :class:MCPToolsetProvider. prefix
namespaces every reported tool name (forwarded to PydanticAI's
MCPServerStreamableHTTP(tool_prefix=...)) so two HTTP MCP servers
with overlapping tool names can coexist on one agent.
Source code in src/murmur/tools/mcp.py
mcp_sse¶
mcp_sse
¶
mcp_sse(
url: str,
*,
headers: Mapping[str, str] | None = None,
allow: Sequence[str] | None = None,
prefix: str | None = None,
) -> MCPToolsetProvider
Build an :class:MCPToolsetProvider over a Server-Sent-Events MCP server.
allow is the optional tool allow-list — see :class:MCPToolsetProvider.
prefix namespaces every reported tool name (forwarded to
MCPServerSSE(tool_prefix=...)).
Source code in src/murmur/tools/mcp.py
Dynamic fan-out¶
Factory + value types for the LLM-callable spawn_agents tool — see
the Agents concept page
for the end-to-end usage pattern.
make_spawn_agents_tool¶
make_spawn_agents_tool
¶
make_spawn_agents_tool(
*,
runtime: AgentRuntime,
template: AgentTemplate,
output_type: type[BaseModel],
max_concurrency: int = 10,
) -> Callable[[list[SpawnSpec]], Awaitable[list[SpawnResult]]]
Build an LLM-callable tool that spawns child agents under template.
| PARAMETER | DESCRIPTION |
|---|---|
runtime
|
The runtime that will dispatch the children. Children are
run via
TYPE:
|
template
|
Bounds what the LLM can spawn. Trust level, model, and tool surface come from the template; the LLM cannot escalate.
TYPE:
|
output_type
|
Output type shared by every child this tool spawns. (Per-child output types — mode B — are a future extension; this factory enforces a single shape today.)
TYPE:
|
max_concurrency
|
Cap on simultaneous in-flight children. Defaults to 10.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Callable[[list[SpawnSpec]], Awaitable[list[SpawnResult]]]
|
An async callable suitable for registration on a |
Callable[[list[SpawnSpec]], Awaitable[list[SpawnResult]]]
|
class: |
Callable[[list[SpawnSpec]], Awaitable[list[SpawnResult]]]
|
and forwarding to the parent agent's |
The returned callable's signature is (specs: list[SpawnSpec]) ->
list[SpawnResult] — PydanticAI's schema introspection turns that
into the tool's JSON schema for the LLM.
Source code in src/murmur/tools/spawn.py
SpawnSpec¶
SpawnSpec
¶
One child to spawn — the shape the LLM picks per fan-out slot.
SpawnResult¶
SpawnResult
¶
One child's outcome — what the parent agent consumes.
name
instance-attribute
¶
The child's :attr:SpawnSpec.name, echoed back so the parent can
correlate without tracking order.
success
instance-attribute
¶
True when the child returned a validated output; False on
spawn / dispatch / validation failure.
output
class-attribute
instance-attribute
¶
The child's output, dumped via Pydantic's model_dump(). None
when success is False. Any here covers the heterogeneous
payload shapes a child's output_type may produce — typing is
statically restored by the parent's downstream handling.
error
class-attribute
instance-attribute
¶
Stringified failure cause when success is False.
Built-in / provider-side tools¶
These are PydanticAI's AbstractBuiltinTool subclasses, re-exported
from murmur.tools so users never import pydantic_ai. They execute
on the LLM provider's infrastructure — Anthropic web search, OpenAI
code execution, Gemini file search, etc. — and bypass the
Murmur ToolExecutor by design. See
Tools — built-in / provider-side
for the executor-bypass caveat.
| Class | Provider | Notes |
|---|---|---|
WebSearchTool |
Anthropic, OpenAI, Gemini, Groq | Native web search; takes max_uses and allowed_domains. |
WebFetchTool |
Anthropic | Fetch a URL and add to the conversation; takes max_uses. |
CodeExecutionTool |
Anthropic, OpenAI, Gemini, Groq | Provider-side sandboxed Python execution. |
FileSearchTool |
OpenAI, Gemini | Search uploaded files / vector store. |
ImageGenerationTool |
OpenAI, Gemini, Groq | Generate images inline. |
MemoryTool |
Anthropic | Persistent memory across conversation turns. |
MCPServerTool |
OpenAI | Provider-managed MCP servers (distinct from Murmur's MCP consume side). |
XSearchTool |
Grok / xAI | X (Twitter) search. |
AbstractBuiltinTool |
– | Base class. Use the concrete subclasses; this is the common type for Agent.builtin_tools. |
from murmur import Agent
from murmur.tools import WebSearchTool, CodeExecutionTool
agent = Agent(
name="researcher",
model="anthropic:claude-sonnet-4-6",
instructions="...",
output_type=Out,
builtin_tools=(
WebSearchTool(max_uses=10),
CodeExecutionTool(),
),
)
For the per-class kwargs, see PydanticAI's built-in tools docs.