Tools & Surface
This page is the practical Go SDK tutorial for the runtime-owned action layer. It shows how to inspect the built-in tool inventory, shape a workflow-specific session surface, attach governance, add MCP tools, and understand what is and is not a clean public customization path today.
What This Page Covers
This page is about the action layer: built-in tools, session shaping, permission-sensitive execution, and MCP extensions. Provider setup, OAuth, capability-provider auth, and Codex login flows belong in Providers & Auth.
If you need provider setup, continue with Providers & Auth. If you want the architectural why behind the separation, continue with Tools & Providers.
Integration Patterns
Keep the built-in inventory, then remove file mutation and shell tools for audit, review, or architecture analysis workflows.
Keep edit and shell tools enabled, but add permission mode and pre-tool governance so mutating actions still flow through host policy.
Attach MCP servers to pull GitHub, issue tracker, CRM, or domain-specific tools into the same runtime loop.
Use one shared client and create multiple session profiles by changing permission mode and unregistering tools per workflow.
The Host Workflow
For Go hosts, the clean path is simple: create one client, inspect what exists, apply workflow-specific trimming per session, then extend or govern the surface where needed. You do not need to fight the runtime to keep the host in control.
Filesystem, shell, browser, planning, memory, notebook, agent, and multimedia tools are registered locally in one canonical inventory.
External tools can be injected through MCP and lower-priority tools can stay deferred until the runtime explicitly discovers them.
Permission mode, read-only metadata, destructive checks, shell hooks, and surface profiles decide what the session may actually execute.
The host can inspect the surface, unregister tools for one session, and let the model work only with the final filtered set.
The clean host pattern is straightforward: create the client, inspect the inventory, define workflow-specific session policies, attach governance, and then let the runtime execute one governed loop.
Deferred tools stay out of the initial surface and are discovered only when the runtime needs them.
The host can refresh external MCP integrations without rebuilding the whole client surface from scratch.
Pick the model, permission mode, and optional MCP servers for the host app.
Use ToolNames() and BuildToolSurface() to see what the runtime is about to expose.
Remove risky tools or change permission mode for one workflow before sending the turn.
Use runtime events and chunk callbacks to keep your UI or backend worker observable.
Bring in external tools and refresh them later without tearing down the whole process.
The runtime still owns prompt, tool calls, permissions, memory, and session persistence coherently.
Step 1: Inspect The Inventory
Start by checking what the runtime already exposes. client.ToolNames() returns the registered primary names. client.BuildToolSurface(ctx) shows the filtered external surface the runtime would expose after registry-level rules are applied.
client, err := sdk.NewClient(&sdk.ClientConfig{
Model: sdk.ModelIdentifier{
Provider: sdk.APIProviderAnthropic,
Model: "claude-sonnet-4-20250514",
},
APIKey: os.Getenv("ANTHROPIC_API_KEY"),
PermissionMode: sdk.PermissionModeOnRequest,
})
if err != nil {
log.Fatal(err)
}
defer client.Close()
fmt.Println(client.ToolNames())
surface, err := client.BuildToolSurface(ctx)
if err != nil {
log.Fatal(err)
}
for _, tool := range surface.Tools {
fmt.Println(tool.Name)
}Step 2: Create A Workflow-Specific Session
Do not destroy the shared client inventory just because one workflow is stricter than another. The practical pattern is to create the session, set the right permission mode, unregister the tools that do not belong in that workflow, and only then submit the task.
session, err := client.CreateSession(ctx)
if err != nil {
log.Fatal(err)
}
defer session.Close()
session.SetPermissionMode(sdk.PermissionModeOnRequest)
for _, blocked := range []string{"bash", "write_file", "edit_file", "apply_patch"} {
_ = session.UnregisterTool(blocked)
}
fmt.Println(session.GetToolNames())
resp, err := session.SubmitMessage(ctx, "Audit the repository and report findings only.")
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.StopReason)type WorkerProfile struct {
Name string
PermissionMode sdk.PermissionMode
RemoveTools []string
}
func NewWorkerSession(ctx context.Context, client *sdk.Client, profile WorkerProfile) (*sdk.Session, error) {
session, err := client.CreateSession(ctx)
if err != nil {
return nil, err
}
session.SetPermissionMode(profile.PermissionMode)
for _, toolName := range profile.RemoveTools {
_ = session.UnregisterTool(toolName)
}
return session, nil
}
reviewSession, err := NewWorkerSession(ctx, client, WorkerProfile{
Name: "review",
PermissionMode: sdk.PermissionModeOnRequest,
RemoveTools: []string{"bash", "write_file", "edit_file", "apply_patch"},
})Step 3: Add Governance For Mutating Tools
Shaping the visible surface is only one half of host control. Execution still goes through permission mode and optional pre-tool hooks. That is the clean SDK-level place to block, rewrite, or strictly review high-risk calls like shell execution and file mutation.
client, err := sdk.NewClient(&sdk.ClientConfig{
Model: sdk.ModelIdentifier{
Provider: sdk.APIProviderAnthropic,
Model: "claude-sonnet-4-20250514",
},
APIKey: os.Getenv("ANTHROPIC_API_KEY"),
PermissionMode: sdk.PermissionModeOnRequest,
PreToolHooks: []sdk.PreToolHookConfig{
{
Matcher: "bash|write_file|edit_file|apply_patch",
Command: "./scripts/pre_tool_guard.sh",
Timeout: 5,
},
},
})- PermissionMode decides the runtime approval posture for the session.
- PreToolHooks let the host allow, deny, halt, or rewrite tool calls before they execute.
- session.SetPermissionMode(...) lets one session become stricter or looser than the client default.
Step 4: Extend The Surface With MCP
When built-ins are not enough, MCP is the clean extension path. You can register servers when the client starts, and later refresh them with client.ReloadMCPServers(ctx, ...) if the external tool surface changes.
servers := []sdk.MCPServerConfig{
{
Name: "github",
Transport: sdk.MCPTransportStdio,
Command: "npx",
Args: []string{"-y", "@modelcontextprotocol/server-github"},
},
}
client, err := sdk.NewClient(&sdk.ClientConfig{
Model: sdk.ModelIdentifier{
Provider: sdk.APIProviderAnthropic,
Model: "claude-sonnet-4-20250514",
},
APIKey: os.Getenv("ANTHROPIC_API_KEY"),
MCPServers: servers,
})
if err != nil {
log.Fatal(err)
}
defer client.Close()
if err := client.ReloadMCPServers(ctx, servers); err != nil {
log.Fatal(err)
}Custom Tool Boundary Today
The public SDK already exposes client.RegisterTool(...), client.RegisterTools(...), and session.RegisterTool(...). But there is an important boundary to understand before you build on that.
// Public SDK surface today:
// - client.ToolNames()
// - client.BuildToolSurface(ctx)
// - client.RegisterTool(...)
// - session.RegisterTool(...)
// - session.UnregisterTool(...)
// - client.ReloadMCPServers(...)
// - ClientConfig.PreToolHooks
//
// Practical guidance:
// Start with built-in tools + MCP + session shaping first.
// Custom tools are possible, but their implementation still follows the
// underlying runtime tool contract rather than a simplified SDK-only builder.If you are integrating Seshat into a product today, start with built-in tools, session shaping, permission governance, and MCP. Custom tools are possible, but the implementation contract still mirrors the runtime tool interface more closely than a dedicated SDK-first builder API.
Inventory Snapshot
These counts come from the current runtime registry: builtin tools first, then the extra agent tools that are only registered once the live engine instance exists.
Builtin registry entries plus engine-wired agent tools.
The initial runtime inventory before later engine-specific additions.
Disabled entries are usually waiting for credentials, capability config, or fuller implementation.
Registered later because they depend on the live engine instance, not only on the builtin registry.
Tool State Semantics
The raw inventory only becomes useful once you understand how the runtime filters it. SurfaceBuilder asks the registry for a candidate surface, then applies permission checks, category filters, read-only or destructive filters, deferred-loading rules, and surface-profile visibility.
| Runtime flag | Meaning | Comes from | Effect on the surface |
|---|---|---|---|
| enabled | The tool is active in the registry and can participate in the runtime surface. | tool.IsEnabled() | The tool may appear in the model-visible surface once the other filters pass. |
| disabled | The tool is registered conceptually but intentionally not active yet. | tool.IsEnabled() == false | The tool is skipped before prompt exposure and execution. |
| read-only | The tool does not modify state for that specific invocation path. | Definition.IsReadOnly plus IsReadOnly(input) | Surface builders and plan mode can treat it differently from mutating tools. |
| requires_permission | The tool enters the permission pipeline before execution. | Definition.RequiresPermission | The user or policy layer may allow, deny, or rewrite access before the call runs. |
| deferred | The tool should stay out of the initial surface and be discovered later. | Definition.ShouldDefer or Definition.IsMCP | When tool search surface mode is enabled, deferred tools stay out of the initial surface and are discovered through tool_search. |
| always-load | The tool should never be hidden by deferred loading. | Definition.AlwaysLoad | The tool remains visible even when deferred loading is active. tool_search is the canonical example. |
| surface profile | The tool may be limited to mono_run or another specific runtime surface. | Definition.Metadata.surface_profiles | A tool can exist in the registry but still be hidden from a given session profile. |
One important detail is deferred loading. When tool search mode is active, deferred tools stay out of the initial model-visible surface and must be discovered through tool_search. If a tool is marked AlwaysLoad, that rule wins and the tool stays visible.
Tool Families And Exact Runtime Flags
The tables below reflect the current runtime metadata for each tool: whether it is enabled, whether it is read-only, and whether it enters the permission pipeline. This is the useful developer view because it follows the actual registry state, not a simplified marketing list.
Filesystem & Process Surface
This is the local execution layer: file reads and writes, patching, shell execution, background jobs, directory traversal, and long-running process monitoring.
| Tool | Category | State | Read-only | Permission | Notes |
|---|---|---|---|---|---|
| apply_patch | filesystem | enabled | no | required | — |
| bash | filesystem | enabled | no | required | Shell execution surface with permission gating and mono-run focus. |
| create_directory | filesystem | enabled | no | required | — |
| edit_file | filesystem | enabled | no | required | — |
| get_file_metadata | filesystem | enabled | yes | not required | — |
| glob | filesystem | enabled | yes | required | — |
| grep | filesystem | enabled | yes | required | — |
| job_kill | filesystem | enabled | no | not required | — |
| job_output | filesystem | enabled | no | not required | — |
| list_directory | filesystem | enabled | yes | not required | — |
| monitor | process | enabled | no | not required | Session-level process monitoring for background execution. |
| read_document_url | filesystem | enabled | yes | required | — |
| read_file | filesystem | enabled | yes | required | — |
| remove_file | filesystem | enabled | no | required | — |
| write_file | filesystem | enabled | no | required | — |
| write_stdin | filesystem | enabled | no | not required | — |
Web & Browser Surface
Seshat separates URL fetching from full browser control. Web fetch/search cover discovery and extraction, while browser_* tools expose a stateful browser session with page, network, and interaction primitives.
| Tool | Category | State | Read-only | Permission | Notes |
|---|---|---|---|---|---|
| browser_click | browser | enabled | no | required | — |
| browser_close_page | browser | enabled | no | not required | — |
| browser_extract | browser | enabled | yes | not required | — |
| browser_get_network_policy | browser | enabled | yes | not required | — |
| browser_list_downloads | browser | enabled | yes | not required | — |
| browser_list_pages | browser | enabled | yes | not required | — |
| browser_navigate | browser | enabled | no | required | — |
| browser_network_list | browser | enabled | yes | not required | — |
| browser_open | browser | enabled | no | required | — |
| browser_press | browser | enabled | no | required | — |
| browser_screenshot | browser | enabled | yes | not required | — |
| browser_scroll | browser | enabled | yes | not required | — |
| browser_search_content | browser | enabled | yes | not required | — |
| browser_select_page | browser | enabled | no | not required | — |
| browser_set_network_policy | browser | enabled | no | not required | — |
| browser_snapshot | browser | enabled | yes | not required | — |
| browser_type | browser | enabled | no | required | — |
| browser_wait | browser | enabled | yes | not required | — |
| web_fetch | web | enabled | yes | not required | Targeted extraction once the runtime already knows the page to inspect. |
| web_search | web | enabled | yes | required | Uses the configured web-search provider and goes through the permission pipeline. |
Code, Notebooks & IDE Hooks
These tools cover code completion, LSP-assisted inspection, and full notebook lifecycle operations from creation to execution and kernel control.
| Tool | Category | State | Read-only | Permission | Notes |
|---|---|---|---|---|---|
| code_complete | code | disabled | no | not required | Fill-in-the-middle style code completion surface; disabled until a completer backend is configured. |
| lsp | code_intelligence | enabled | no | not required | — |
| notebook_create | notebook | enabled | no | required | — |
| notebook_edit | notebook | enabled | no | required | — |
| notebook_execute | notebook | enabled | no | required | — |
| notebook_kernel | notebook | enabled | no | required | — |
| notebook_read | notebook | enabled | yes | not required | — |
| notebook_run | notebook | enabled | no | required | — |
| notebook_write | notebook | enabled | no | required | — |
Planning, Tasks & Runtime Control
These tools control how the agent works: ask-user pauses, plan mode transitions, task objects, goal tracking, permission requests, and the meta discovery surface.
| Tool | Category | State | Read-only | Permission | Notes |
|---|---|---|---|---|---|
| ask_user_question | interaction | enabled | yes | not required | — |
| create_goal | goal | enabled | no | not required | — |
| enter_plan_mode | planning | enabled | yes | required | — |
| exit_plan_mode | mode | enabled | no | required | — |
| get_goal | goal | enabled | yes | not required | — |
| request_permissions | permissions | enabled | no | required | — |
| submit_plan | mode | disabled | no | not required | — |
| task_create | task | enabled | no | not required | — |
| task_get | task | enabled | no | not required | — |
| task_list | task | enabled | no | not required | — |
| task_stop | task | enabled | no | not required | — |
| task_update | task | enabled | no | not required | — |
| tool_search | meta | disabled | yes | not required | Special discovery helper. It is marked AlwaysLoad in the registry even though runtime enablement is optimistic. |
| update_goal | goal | enabled | no | not required | — |
Memory & Retrieval
Long-term memory and retrieval are explicit tools, not hidden side effects. The runtime can write to knowledge-graph memory or query indexed corpora through the RAG surface.
| Tool | Category | State | Read-only | Permission | Notes |
|---|---|---|---|---|---|
| memory_add_observations | memory | disabled | no | not required | Backed by the LongTermMemory service rather than by raw prompt stuffing. |
| memory_create_entities | memory | disabled | no | not required | Backed by the LongTermMemory service rather than by raw prompt stuffing. |
| memory_open_nodes | memory | disabled | yes | not required | Backed by the LongTermMemory service rather than by raw prompt stuffing. |
| memory_search_nodes | memory | disabled | yes | not required | Backed by the LongTermMemory service rather than by raw prompt stuffing. |
| rag_ingest | rag | disabled | no | required | Backed by the configured RAG service and corpus index. |
| rag_search | rag | disabled | yes | not required | Backed by the configured RAG service and corpus index. |
Skills, MCP & Worktree Extensions
This family covers runtime extensibility: generic MCP access, installed Seshat skills, the skill execution tool, and isolated worktree helpers.
| Tool | Category | State | Read-only | Permission | Notes |
|---|---|---|---|---|---|
| enter_worktree | worktree | enabled | no | required | — |
| exit_worktree | worktree | enabled | no | required | — |
| mcp | mcp | enabled | yes | required | Gateway tool for configured MCP servers. Separate MCP-loaded tools can also appear as runtime-discovered surface entries. |
| seshat_list_skills | runtime-specific | enabled | yes | not required | Skill package introspection helpers used to list, read, or validate installed Seshat skills. |
| seshat_read_skill | runtime-specific | enabled | yes | not required | Skill package introspection helpers used to list, read, or validate installed Seshat skills. |
| seshat_validate_skill | runtime-specific | enabled | yes | not required | Skill package introspection helpers used to list, read, or validate installed Seshat skills. |
| skill | runtime-specific | enabled | no | not required | Executes a resolved skill directly inside the main conversation loop. |
Agents & Delegation
Agent control is split between builtin coordination tools and engine-wired delegation tools that are only registered once the live engine instance exists.
| Tool | Category | State | Read-only | Permission | Notes |
|---|---|---|---|---|---|
| agent | agent | enabled | no | required | Registered later in sdk.NewClient because it needs the live engine instance. |
| close_agent | agents | enabled | no | not required | — |
| list_agents | agents | enabled | yes | not required | — |
| resume_agent | agents | enabled | no | not required | Registered later in sdk.NewClient because it needs the live engine instance. |
| send_agent_message | agents | enabled | no | not required | — |
| spawn_agent | agents | enabled | no | not required | Registered later in sdk.NewClient because it needs the live engine instance. |
| wait_agent | agents | enabled | yes | not required | — |
Media & Multimodal Capabilities
These tools are capability-provider driven. They are usually disabled until the matching image or audio backend is configured.
| Tool | Category | State | Read-only | Permission | Notes |
|---|---|---|---|---|---|
| generate_image | creative | disabled | no | not required | Enabled only when an image-generation provider is configured. |
| speech_to_text | audio | disabled | no | not required | Enabled only when the corresponding audio provider is configured. |
| text_to_speech | audio | disabled | no | not required | Enabled only when the corresponding audio provider is configured. |
Math & Analysis Helpers
Fast deterministic helpers for calculation, units, statistics, and financial analysis. These tools stay cheap, local, and read-only.
| Tool | Category | State | Read-only | Permission | Notes |
|---|---|---|---|---|---|
| calculator | math | enabled | yes | not required | — |
| financial_calc | math | enabled | yes | not required | — |
| statistics | math | enabled | yes | not required | — |
| unit_convert | math | enabled | yes | not required | — |
VCS, Social & Notification Integrations
This family mixes community data tools, outbound messaging tools, and VCS helpers. Several entries are present in the surface design but remain disabled until implementation or credentials are ready.
| Tool | Category | State | Read-only | Permission | Notes |
|---|---|---|---|---|---|
| devto_article | social | enabled | yes | not required | — |
| devto_feed | social | enabled | yes | not required | — |
| devto_publish | social | enabled | no | required | — |
| discord_send | notifications | disabled | no | required | Compiled into the surface design, but disabled until credentials and/or implementation are ready. |
| email_send | notifications | disabled | no | required | Compiled into the surface design, but disabled until credentials and/or implementation are ready. |
| git_branch | vcs | disabled | no | not required | Present in the runtime inventory, but currently disabled in the builtin surface. |
| git_commit | vcs | disabled | no | required | Present in the runtime inventory, but currently disabled in the builtin surface. |
| git_diff | vcs | disabled | no | not required | Present in the runtime inventory, but currently disabled in the builtin surface. |
| git_log | vcs | disabled | no | not required | Present in the runtime inventory, but currently disabled in the builtin surface. |
| git_status | vcs | disabled | no | not required | Present in the runtime inventory, but currently disabled in the builtin surface. |
| hn_item | social | enabled | yes | not required | — |
| hn_search | social | enabled | yes | not required | — |
| hn_stories | social | enabled | yes | not required | — |
| slack_send | notifications | disabled | no | required | Compiled into the surface design, but disabled until credentials and/or implementation are ready. |
| telegram_send | notifications | disabled | no | required | Compiled into the surface design, but disabled until credentials and/or implementation are ready. |
| whatsapp_send | social | disabled | no | required | Compiled into the surface design, but disabled until credentials and/or implementation are ready. |
Related Pages
Continue with Providers & Auth for provider setup, OAuth, and Codex. For the extensibility side, continue with Skills and MCP.