Write an Authored Tool
Authored tools are public Agent Core files that the host tool runtime can expose
to the model. They live under the tool root configured in the concrete core's
agent.yaml.
The source assistant core uses:
slots:
tools: agent/tools
With that setting, a tool named project_note lives at:
agent/tools/project_note/
tool.yaml
module.py
Authored tools are not input or output slots. Do not add them to
agent/pipelines.yaml.
Define tool.yaml
Create agent/tools/project_note/tool.yaml:
entrypoint: module:execute
description: "Return a short project note."
input_schema:
type: object
properties:
topic:
type: string
additionalProperties: false
risk: low
capability: tool.call:project_note
approval_policy: auto
display_policy: summary
model_output_policy: content
capabilities: []
The tool id is the directory name. The model sees the description and
input_schema when the host exposes the tool.
Choose an id that does not collide with a selected builtin tool or a discovered MCP tool. Builtin/authored collisions fail core loading, while MCP collisions fail final catalog construction. The error lists both provenances; rename the authored tool instead of relying on source priority.
The singular capability is the primary registry capability for this tool's
metadata and approval policy. The capabilities list is different: it declares
capabilities that the tool implementation may require through
ctx.capability.require(...).
Implement module.py
Create agent/tools/project_note/module.py:
from demiurge.sdk import ToolResult
def execute(ctx, args):
topic = args.get("topic") or "project"
return ToolResult(content=f"Note about {topic}: keep changes scoped.")
The default authored tool entrypoint is module:execute.
Declare Effect Capabilities When Needed
If the tool implementation performs a host-guarded effect, add that effect to
capabilities and require it in code.
capability: tool.call:workspace_note
capabilities:
- fs.read
from pathlib import Path
from demiurge.sdk import ToolResult
def execute(ctx, args):
ctx.capability.require("fs.read", slot_path=ctx.slot_path)
path = Path(ctx.workspace) / "README.md"
return ToolResult(content=path.read_text(encoding="utf-8")[:500])
Declaring capability does not grant filesystem, terminal, network, state, or
agent authority. Grant only the specific effect capabilities the implementation
uses.
Override Metadata from agent.yaml
Use tools.metadata when you need to hide a tool or override registry metadata
without editing the tool directory:
tools:
metadata:
project_note:
approval_policy: prompt
risk: medium
For authored tools, metadata overrides can lower or raise risk and approval policy. Built-in tools are more restrictive: core metadata cannot lower their risk or weaken their approval policy.
Verify
Run:
uv run demiurge init --check
uv run demiurge --provider fake
Inside the TUI:
/tools
The tool should appear as an authored tool. If it does not, confirm that:
agent.yamlhasslots.tools: agent/tools.- The tool directory contains
tool.yaml. tool.yamluses only supported fields.- The tool id matches the directory name.
- The tool id does not collide with a builtin or MCP model-visible name.