Documentation
¶
Overview ¶
Package executors provides tool executor implementations for the agentic system.
BashExecutor runs shell commands. When a remote runner is configured (SANDBOX_URL), commands execute inside the remote sandbox container via the runner client. Otherwise, they run locally via os/exec with sensitive environment variables stripped.
The remote dispatch path is fronted by the Runner interface so downstream products can supply custom routing logic (per-tenant devcontainers, load-balancing across sandbox replicas, attestation-aware routing, A/B testing) without wrapping BashExecutor. *runner.Client is the default implementation; product shells inject alternates via WithRunner. This is the per-call extension point the forthcoming capability-aware execution-environment substrate (ADR-052, see docs/proposals/sandbox-substrate.md) plugs into.
Ported from semspec/tools/bash.
Package executors provides tool executor implementations for the agentic-tools component.
Package executors hosts the concrete tool implementations and their wire-to-registry entry points.
Stateless tools (bash, http_request, web_search) wire from env vars alone. Stateful tools (query_entity, read_loop_result, decide) need runtime deps (NATS KV buckets, platform identity) which only exist after the binary has initialised streams/buckets — so their wire functions take explicit arguments rather than registering at init() time.
The single caller of RegisterBuiltins is main.go, after ensureStreams and before component.Start. The registry is constructed by main and passed in explicitly — there is no package-level singleton.
Index ¶
- Variables
- func RegisterBuiltins(ctx context.Context, reg *agentictools.ExecutorRegistry, deps ToolDependencies) error
- type BashExecutor
- type BashOption
- type FlowEngineManager
- type FlowExecutor
- type FlowLifecycleExecutor
- type FlowManager
- type FlowTemplateExecutor
- type FlowTemplateManager
- type GraphQueryExecutor
- type HTTPRequestExecutor
- type HTTPRequestOption
- func WithHTTPClock(now func() time.Time) HTTPRequestOption
- func WithHTTPLogger(l *slog.Logger) HTTPRequestOption
- func WithHTTPPlatform(p component.PlatformMeta) HTTPRequestOption
- func WithHTTPTimeout(d time.Duration) HTTPRequestOption
- func WithHTTPTriplePublisher(p agentictools.TriplePublisher) HTTPRequestOption
- type JetStreamKVAdapter
- type KVEntry
- type KVGetter
- type NATSQuerier
- type PersonaExecutor
- type PersonaManager
- type RuleExecutor
- type RuleManager
- type Runner
- type SearchGraphExecutor
- type SearchGraphOption
- type StubWebSearchExecutor
- type SummarizeGraphExecutor
- type SummarizeGraphOption
- type ToolDependencies
- type WebSearchExecutor
- type WebSearchOption
Constants ¶
This section is empty.
Variables ¶
var BuiltinGroupKeys = []string{
"bash",
"web_search",
"http_request",
"read_loop_result",
"decide",
"emit_diagnosis",
"emit_lesson",
"write_todos",
"scratchpad",
"summarize_graph",
"search_graph",
"flow_monitor",
"graph_query",
"rules",
"flows",
"personas",
"flow_templates",
"component_catalog",
"flow_lifecycle",
}
BuiltinGroupKeys is the closed set of valid SkipBuiltins entries. For single-tool register functions the key matches the tool name; for multi-tool register functions the key is a domain label that skips the whole group as a unit (the registry can't partially register one executor's ListTools() output).
The slice is exported so external callers (and tests) can iterate for validation, documentation, or "skip everything except X" derivation. Order is stable for golden-test reproducibility.
var ErrKeyNotFound = errs.ErrKeyNotFound
ErrKeyNotFound is returned when a key is not found in the KV store.
Functions ¶
func RegisterBuiltins ¶
func RegisterBuiltins(ctx context.Context, reg *agentictools.ExecutorRegistry, deps ToolDependencies) error
RegisterBuiltins wires every tool this package owns into the supplied registry. Errors from individual register_* functions are aggregated via errors.Join so a misconfigured deployment sees every collision on a single boot, not just the first. The aggregate error is returned to the caller (main.go) which surfaces it via its normal error-return path — no panics, just a non-zero exit.
Two distinct failure shapes:
- Pre-condition skips (nil manager, missing env var, KV bucket unreachable) are intentional disable paths. They log and proceed — not an error from this function's perspective.
- Registry-level failures (duplicate tool names, invalid args) are misconfigurations that should block boot. Each register_* returns them; we join them and return the aggregate.
Types ¶
type BashExecutor ¶
type BashExecutor struct {
// contains filtered or unexported fields
}
BashExecutor runs shell commands locally or via a Runner (which routes to a remote sandbox container — see SANDBOX_URL for the URL-based default, WithRunner for custom routing).
func NewBashExecutor ¶
func NewBashExecutor(workDir, sandboxURL string, opts ...BashOption) *BashExecutor
NewBashExecutor creates a bash executor. If sandboxURL is non-empty, commands are routed to the sandbox container via the default *runner.Client. Pass WithRunner to inject a custom Runner instead; when supplied, it overrides the URL-based default.
func NewBashExecutorFromEnv ¶
func NewBashExecutorFromEnv() *BashExecutor
NewBashExecutorFromEnv creates a bash executor using environment variables. SANDBOX_URL enables sandbox mode. Work directory defaults to cwd.
func (*BashExecutor) Execute ¶
func (e *BashExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute runs a shell command and returns the output.
func (*BashExecutor) ListTools ¶
func (e *BashExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the bash tool definition.
Observability note (gh#146): when a bash command performs an external fetch (curl/wget/httpie), the resulting trajectory step carries a first-class url_fetched attribute derived from the command string (see agentic.BashStepURLs / ExtractFetchedURLs), so citation/audit/governance dashboards can filter and count external reach independently of generic shell activity.
type BashOption ¶
type BashOption func(*BashExecutor)
BashOption configures a BashExecutor.
func WithBashTimeout ¶
func WithBashTimeout(d time.Duration) BashOption
WithBashTimeout overrides the default command timeout (120s).
func WithRunner ¶
func WithRunner(r Runner) BashOption
WithRunner overrides the runner constructed from sandboxURL. When provided, sandboxURL is ignored; the supplied Runner handles all remote dispatch. Mutually exclusive with the URL-based constructor; either call NewBashExecutor("", "", WithRunner(custom)) or pass a URL and omit the option. Passing the untyped nil is treated as "no override" (URL-based default applies if a URL was given). A typed-nil wrapped in a Runner interface value — e.g., `var r Runner = (*runner.Client)(nil); WithRunner(r)` — is NOT detected and will panic on first Exec; construct your Runner before passing it in.
type FlowEngineManager ¶
type FlowEngineManager interface {
Deploy(ctx context.Context, flowID string) error
Start(ctx context.Context, flowID string) error
Stop(ctx context.Context, flowID string) error
Undeploy(ctx context.Context, flowID string) error
}
FlowEngineManager is the subset of the flow engine's lifecycle surface that FlowLifecycleExecutor needs. Declared as an interface so tests can substitute an in-memory fake without depending on the full *flowengine.Engine type — which itself transitively pulls in the component registry, NATS, and the metrics registry. *flowengine.Engine satisfies it by duck typing; signatures match engine/engine.go:91, 135, 173, 211 verbatim.
Deploy / Start / Stop / Undeploy mirror the engine's runtime-state transitions: not_deployed → deployed → running → stopped → undeployed. Errors from the engine surface verbatim — including transition pre-condition violations — so the agent gets the engine's wrapped diagnostic rather than a tool-side rephrasing.
type FlowExecutor ¶
type FlowExecutor struct {
// contains filtered or unexported fields
}
FlowExecutor implements CRUD tools for flow definitions. Mirrors RuleExecutor's shape (one executor per Pattern-B type, dispatching on ToolCall.Name to the right Manager method).
func NewFlowExecutor ¶
func NewFlowExecutor(manager FlowManager) *FlowExecutor
NewFlowExecutor creates a flow management executor.
func (*FlowExecutor) Execute ¶
func (e *FlowExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute dispatches flow CRUD tool calls by name.
func (*FlowExecutor) ListTools ¶
func (e *FlowExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the five flow-CRUD tool definitions. Flow is a structured object (nodes, connections, runtime state, timestamps); the tool schema accepts a JSON object via `flow` parameter so LLMs can construct or edit definitions without a hand-crafted schema per field. Validation happens when the Manager unmarshals + Validate()s the payload.
type FlowLifecycleExecutor ¶
type FlowLifecycleExecutor struct {
// contains filtered or unexported fields
}
FlowLifecycleExecutor implements the runtime lifecycle tools that complement FlowExecutor's CRUD surface. CRUD writes the flow definition; lifecycle moves the deployed instance through its state machine. The two are separate executors so an operator can allow authoring (create_flow / update_flow) without enabling deployment (deploy_flow / start_flow), or vice-versa, via SkipBuiltins or approval_required gating.
Companion to ADR-042 (semteams): coordinator persona issues create_flow → deploy_flow → start_flow at runtime; ComponentManager picks up the deployed flow from semstreams_config KV and spins components dynamically.
func NewFlowLifecycleExecutor ¶
func NewFlowLifecycleExecutor(manager FlowEngineManager) *FlowLifecycleExecutor
NewFlowLifecycleExecutor creates a flow lifecycle executor.
func (*FlowLifecycleExecutor) Execute ¶
func (e *FlowLifecycleExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute dispatches flow lifecycle tool calls by name.
func (*FlowLifecycleExecutor) ListTools ¶
func (e *FlowLifecycleExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the four lifecycle tool definitions. All four take the same single required parameter (flow_id) — the lifecycle is stateless from the tool's perspective; the engine owns the transition pre-condition checks and surfaces violations as errors.
type FlowManager ¶
type FlowManager interface {
Create(ctx context.Context, flow *flowstore.Flow) error
Update(ctx context.Context, flow *flowstore.Flow) error
Delete(ctx context.Context, id string) error
Get(ctx context.Context, id string) (*flowstore.Flow, error)
List(ctx context.Context) ([]*flowstore.Flow, error)
}
FlowManager is the subset of flowstore.Manager that FlowExecutor needs. Declared here so tests can substitute an in-memory fake without depending on the full *flowstore.Manager type. *flowstore.Manager satisfies it by duck typing.
type FlowTemplateExecutor ¶
type FlowTemplateExecutor struct {
// contains filtered or unexported fields
}
FlowTemplateExecutor implements Pattern-B CRUD plus an instantiate_flow_template tool that renders a template into a concrete flowstore.Flow using caller-supplied parameters. Instantiate is NOT stored — the coordinator still has to call create_flow to persist the resulting flow, which goes through flowstore.Manager's validation. Keeping render + persist separate lets the coordinator inspect the rendered flow before committing.
func NewFlowTemplateExecutor ¶
func NewFlowTemplateExecutor(manager FlowTemplateManager) *FlowTemplateExecutor
NewFlowTemplateExecutor creates a flow-template management executor.
func (*FlowTemplateExecutor) Execute ¶
func (e *FlowTemplateExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute dispatches flow-template tool calls by name.
func (*FlowTemplateExecutor) ListTools ¶
func (e *FlowTemplateExecutor) ListTools() []agentic.ToolDefinition
ListTools returns six tools: five CRUD + instantiate.
type FlowTemplateManager ¶
type FlowTemplateManager interface {
Create(ctx context.Context, t *flowtemplate.Template) error
Update(ctx context.Context, t *flowtemplate.Template) error
Delete(ctx context.Context, id string) error
Get(ctx context.Context, id string) (*flowtemplate.Template, error)
List(ctx context.Context) (map[string]*flowtemplate.Template, error)
}
FlowTemplateManager is the subset of flowtemplate.Manager that the executor needs. Declared here so tests can substitute in-memory fakes.
type GraphQueryExecutor ¶
type GraphQueryExecutor struct {
// contains filtered or unexported fields
}
GraphQueryExecutor executes graph queries against the ENTITY_STATES KV bucket.
func NewGraphQueryExecutor ¶
func NewGraphQueryExecutor(kvGetter KVGetter) *GraphQueryExecutor
NewGraphQueryExecutor creates a new GraphQueryExecutor with the given KV getter.
func (*GraphQueryExecutor) Execute ¶
func (e *GraphQueryExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute executes a tool call and returns the result.
func (*GraphQueryExecutor) ListTools ¶
func (e *GraphQueryExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the tool definitions provided by this executor.
type HTTPRequestExecutor ¶
type HTTPRequestExecutor struct {
// contains filtered or unexported fields
}
HTTPRequestExecutor handles http_request tool calls.
Triple emission is optional (mirrors WebSearchExecutor): when a non-nil TriplePublisher is supplied via WithHTTPTriplePublisher, each successful 2xx/3xx fetch additionally emits a fixed set of predicates onto an agent.web.observation entity plus a back-link triple onto the calling loop entity. Non-2xx responses (≥400) do not emit — the graph claim is "we observed this URL's content" and a 4xx/5xx isn't that observation. Per-triple failures log + counter + continue (semstreams.agentic_tool_web.emit_failures_total).
func NewHTTPRequestExecutor ¶
func NewHTTPRequestExecutor(opts ...HTTPRequestOption) *HTTPRequestExecutor
NewHTTPRequestExecutor creates an HTTP request executor.
func (*HTTPRequestExecutor) Execute ¶
func (e *HTTPRequestExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute handles an http_request tool call.
func (*HTTPRequestExecutor) ListTools ¶
func (e *HTTPRequestExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the http_request tool definition.
type HTTPRequestOption ¶
type HTTPRequestOption func(*HTTPRequestExecutor)
HTTPRequestOption configures the executor.
func WithHTTPClock ¶
func WithHTTPClock(now func() time.Time) HTTPRequestOption
WithHTTPClock replaces the time source the executor stamps onto fetched_at / triple timestamps. nil-safe.
func WithHTTPLogger ¶
func WithHTTPLogger(l *slog.Logger) HTTPRequestOption
WithHTTPLogger replaces the default logger (slog.Default()). nil-safe.
func WithHTTPPlatform ¶
func WithHTTPPlatform(p component.PlatformMeta) HTTPRequestOption
WithHTTPPlatform supplies the platform identity used to build observation entity IDs and resolve the calling loop's entity ID. Required when publisher is non-nil; ignored otherwise.
func WithHTTPTimeout ¶
func WithHTTPTimeout(d time.Duration) HTTPRequestOption
WithHTTPTimeout overrides the default request timeout (30s).
func WithHTTPTriplePublisher ¶
func WithHTTPTriplePublisher(p agentictools.TriplePublisher) HTTPRequestOption
WithHTTPTriplePublisher enables graph emission. nil disables emission (default).
type JetStreamKVAdapter ¶
type JetStreamKVAdapter struct {
// contains filtered or unexported fields
}
JetStreamKVAdapter adapts a jetstream.KeyValue to our KVGetter interface.
func NewJetStreamKVAdapter ¶
func NewJetStreamKVAdapter(kv any) *JetStreamKVAdapter
NewJetStreamKVAdapter creates a new adapter for jetstream.KeyValue. Usage: NewJetStreamKVAdapter(kvBucket) where kvBucket is a jetstream.KeyValue
type KVGetter ¶
KVGetter defines the minimal interface needed to query entities from a KV store. This allows for easier testing and decouples the executor from the full jetstream.KeyValue interface.
type NATSQuerier ¶
type NATSQuerier interface {
Request(ctx context.Context, subject string, data []byte, timeout time.Duration) ([]byte, error)
// RequestClassified is the gh#93 path that surfaces handler
// errors via err return as *errs.ClassifiedError. Test mocks
// can synthesize via Request + natsclient.ClassifyReply against
// a nats.Msg{Data: ...} (matches the legacy-body-prefix
// fallback path).
RequestClassified(ctx context.Context, subject string, data []byte, timeout time.Duration) ([]byte, error)
}
NATSQuerier is the narrow interface SummarizeGraphExecutor and SearchGraphExecutor use to round-trip NATS requests. Production satisfies it with *natsclient.Client; tests substitute an in- memory recorder.
type PersonaExecutor ¶
type PersonaExecutor struct {
// contains filtered or unexported fields
}
PersonaExecutor implements CRUD tools for prompt personas. Same shape as RuleExecutor and FlowExecutor per ADR-029.
func NewPersonaExecutor ¶
func NewPersonaExecutor(manager PersonaManager) *PersonaExecutor
NewPersonaExecutor creates a persona management executor.
func (*PersonaExecutor) Execute ¶
func (e *PersonaExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute dispatches persona CRUD tool calls by name.
func (*PersonaExecutor) ListTools ¶
func (e *PersonaExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the five persona-CRUD tool definitions.
type PersonaManager ¶
type PersonaManager interface {
Create(ctx context.Context, p *persona.Persona) error
Update(ctx context.Context, p *persona.Persona) error
Delete(ctx context.Context, id string) error
Get(ctx context.Context, id string) (*persona.Persona, error)
List(ctx context.Context) (map[string]*persona.Persona, error)
}
PersonaManager is the subset of persona.Manager that PersonaExecutor needs. Declared here so tests can substitute in-memory fakes — same pattern as RuleManager and FlowManager.
type RuleExecutor ¶
type RuleExecutor struct {
// contains filtered or unexported fields
}
RuleExecutor implements CRUD tools for the rule engine.
func NewRuleExecutor ¶
func NewRuleExecutor(manager RuleManager) *RuleExecutor
NewRuleExecutor creates a rule management executor.
func (*RuleExecutor) Execute ¶
func (e *RuleExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute dispatches rule tool calls.
func (*RuleExecutor) ListTools ¶
func (e *RuleExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the rule management tool definitions.
type RuleManager ¶
type RuleManager interface {
SaveRule(ctx context.Context, ruleID string, ruleDef rule.Definition) error
DeleteRule(ctx context.Context, ruleID string) error
GetRule(ctx context.Context, ruleID string) (*rule.Definition, error)
ListRules(ctx context.Context) (map[string]rule.Definition, error)
}
RuleManager is the subset of rule.ConfigManager needed by RuleExecutor.
type Runner ¶
type Runner interface {
Exec(ctx context.Context, taskID, command string, timeoutMs int) (*runner.ExecResult, error)
}
Runner is the per-call interface BashExecutor uses to dispatch commands to a remote sandbox server. *runner.Client satisfies it (default, constructed from sandboxURL). Product shells supply custom implementations via WithRunner for per-call routing — e.g., attestation-aware routing to per-tenant devcontainers, load-balancing across replicas, or A/B testing alternate sandbox backends. This is the framework extension point the forthcoming capability-aware execution-environment substrate (ADR-052) builds on; the interface itself is product-agnostic and carries no devcontainer, attestation, or tenancy concepts.
type SearchGraphExecutor ¶
type SearchGraphExecutor struct {
// contains filtered or unexported fields
}
SearchGraphExecutor implements the search_graph tool. Thin wrapper over the graph.query.searchGraph server-side resolver added in PR #54 — natural-language search via GraphRAG with a semantic- search fallback when classifier-routed strategies return empty.
Read-only: no graph emission. The response from the server-side resolver is a GlobalSearchResponse which the tool formats for LLM consumption (answer text + entity digests + community summaries + degraded-banner when the fallback fired).
func NewSearchGraphExecutor ¶
func NewSearchGraphExecutor(natsClient NATSQuerier, opts ...SearchGraphOption) *SearchGraphExecutor
NewSearchGraphExecutor creates the executor. natsClient must be non-nil — without it the tool can't reach the server-side resolver.
func (*SearchGraphExecutor) Execute ¶
func (e *SearchGraphExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute routes the tool call.
func (*SearchGraphExecutor) ListTools ¶
func (e *SearchGraphExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the search_graph definition. The description names search-before-query as the canonical discovery pattern (matches semspec's policy at semspec/tools/workflow/graph.go). Required query argument; level + max_communities are passthrough tuning knobs forwarded to the server-side globalSearch path.
type SearchGraphOption ¶
type SearchGraphOption func(*SearchGraphExecutor)
SearchGraphOption configures a SearchGraphExecutor.
func WithSearchGraphTimeout ¶
func WithSearchGraphTimeout(d time.Duration) SearchGraphOption
WithSearchGraphTimeout overrides the default request timeout.
type StubWebSearchExecutor ¶
type StubWebSearchExecutor struct{}
StubWebSearchExecutor returns canned search results when no Brave API key is available. Keeps web_search in the tool list so researcher-role agents and E2E fixtures work without external API dependencies.
func NewStubWebSearchExecutor ¶
func NewStubWebSearchExecutor() *StubWebSearchExecutor
NewStubWebSearchExecutor creates a stub that returns canned search results.
func (*StubWebSearchExecutor) Execute ¶
func (e *StubWebSearchExecutor) Execute(_ context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute returns canned search results for any query.
func (*StubWebSearchExecutor) ListTools ¶
func (e *StubWebSearchExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the web_search tool definition.
type SummarizeGraphExecutor ¶
type SummarizeGraphExecutor struct {
// contains filtered or unexported fields
}
SummarizeGraphExecutor implements the summarize_graph tool. Thin wrapper over the graph.query.summary server-side resolver added in PR #54 — solves the chicken-and-egg problem where existing query_* tools need known IDs to start, by giving agents a discovery surface (entity types, predicate counts, example IDs per type) without requiring any pre-existing context.
Read-only: emits no graph state, takes no LoopID, requires no platform identity. Pure retrieval + formatting.
func NewSummarizeGraphExecutor ¶
func NewSummarizeGraphExecutor(natsClient NATSQuerier, opts ...SummarizeGraphOption) *SummarizeGraphExecutor
NewSummarizeGraphExecutor creates the executor. natsClient must be non-nil — without it the tool can't reach the server-side resolver.
func (*SummarizeGraphExecutor) Execute ¶
func (e *SummarizeGraphExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute routes the tool call.
func (*SummarizeGraphExecutor) ListTools ¶
func (e *SummarizeGraphExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the summarize_graph definition. The description teaches the discovery-before-query pattern that semspec / semteams rely on. Single optional bool argument; predicate facet defaults on because that's the more useful default for first-call discovery.
type SummarizeGraphOption ¶
type SummarizeGraphOption func(*SummarizeGraphExecutor)
SummarizeGraphOption configures a SummarizeGraphExecutor.
func WithSummarizeGraphTimeout ¶
func WithSummarizeGraphTimeout(d time.Duration) SummarizeGraphOption
WithSummarizeGraphTimeout overrides the default request timeout.
type ToolDependencies ¶
type ToolDependencies struct {
NATSClient *natsclient.Client
MutationClient *projection.MutationClient
Platform component.PlatformMeta
Logger *slog.Logger
RuleManager RuleManager // Pattern-B step 1
FlowManager FlowManager // Pattern-B step 2
PersonaManager PersonaManager // Pattern-B step 3
FlowTemplateManager FlowTemplateManager // Pattern-B step 4
ComponentRegistry *component.Registry // Pattern-B step 5; nil → list_components skipped
FlowEngineManager FlowEngineManager // Pattern-B step 6; nil → flow_lifecycle skipped
// LoopsBucket is the NATS KV bucket name holding agent-loop state.
// read_loop_result + flow_monitor both read from it. Empty falls back
// to "AGENT_LOOPS". One bucket per process — wiring is boot-time so
// the name is frozen at RegisterBuiltins for the lifetime of the
// process.
LoopsBucket string
// RestrictedDecideActions is the deployment-level decide-action
// restriction policy (gh#239): decide action names barred for EVERY
// coordinator task (front-door and rule-spawned), composing with and
// taking precedence over the per-task action_allowlist. Sourced from
// the agentic-tools component config's restricted_decide_actions at
// boot (main.go) and frozen for the process lifetime, like LoopsBucket.
// nil/empty = permissive default. Vocabulary-agnostic: a product shell
// maps its run mode (e.g. autonomous) onto this list.
RestrictedDecideActions []string
// SkipBuiltins is the list of builtin group keys to NOT register.
// Product shells set this when they want to register their own
// implementation under a canonical tool name (e.g., a chain-scoped
// `bash` wrapper for sandbox isolation).
//
// Valid group keys are defined in BuiltinGroupKeys. Unknown names
// cause RegisterBuiltins to return an error before any registration
// happens — typos surface loudly at boot, not silently as "wait,
// why isn't my replacement tool being called?".
//
// For single-tool registrations (e.g., bash, decide), the group key
// IS the tool name. For multi-tool registrations (e.g., graph_query
// advertises five query_* tools, rules advertises five rule_* CRUD
// tools), the group key is the register-function's domain label
// and skips all tools registered by that function as a unit. See
// BuiltinGroupKeys for the full mapping.
//
// Empty/nil = today's behaviour: every builtin registers.
SkipBuiltins []string
}
ToolDependencies carries the runtime inputs the tool-registration functions need. Using a struct rather than a growing positional arg list follows the project convention (memory: feedback_go_signatures — "4+ args → request struct"). Adding a new Pattern-B manager in the future means adding a field here, not shifting every call site.
Zero values are legal on optional fields:
- Logger nil → slog.Default()
- NATSClient nil → stateful tools (read_loop_result, decide, query_entity) are skipped
- RuleManager nil → rule CRUD tools are skipped
- ComponentRegistry nil → list_components skipped (Pattern-B step 5)
- RestrictedDecideActions nil/empty → permissive default (no decide action restricted)
- SkipBuiltins nil/empty → all builtins register (today's behaviour)
Platform is a value type (not pointer) because PlatformMeta is a small POD; the empty value is still safe for the decide tool to use.
type WebSearchExecutor ¶
type WebSearchExecutor struct {
// contains filtered or unexported fields
}
WebSearchExecutor implements the web_search agentic tool.
Triple emission is optional: when a non-nil TriplePublisher is supplied via WithWebSearchTriplePublisher, each successful search additionally emits 6 triples per result onto an agent.web.observation entity plus a back-link triple onto the calling loop entity. When the publisher is nil the executor behaves exactly as it did pre-emission — text-only return, no graph writes. Per-result emission errors are logged and counted (semstreams.agentic_tool_web.emit_failures_total) but never fail the tool, because graph emission is opportunistic substrate observation, not the tool's primary LLM-facing contract. This diverges from decide / write_todos where the triples ARE the contract.
func NewWebSearchExecutor ¶
func NewWebSearchExecutor(apiKey string, opts ...WebSearchOption) *WebSearchExecutor
NewWebSearchExecutor creates a web search executor backed by the Brave Search API. The variadic options enable opt-in features (triple emission, custom logger/clock) without disturbing legacy call sites that pass only the API key.
func (*WebSearchExecutor) Execute ¶
func (e *WebSearchExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute dispatches tool calls.
func (*WebSearchExecutor) ListTools ¶
func (e *WebSearchExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the web_search tool definition.
type WebSearchOption ¶
type WebSearchOption func(*WebSearchExecutor)
WebSearchOption configures a WebSearchExecutor. All options are optional; the executor works with just an apiKey.
func WithWebSearchClock ¶
func WithWebSearchClock(now func() time.Time) WebSearchOption
WithWebSearchClock replaces the time source the executor stamps onto observed_at / triple timestamps. nil-safe. Tests use this for deterministic timestamp assertions; production should not.
func WithWebSearchLogger ¶
func WithWebSearchLogger(l *slog.Logger) WebSearchOption
WithWebSearchLogger replaces the default logger (slog.Default()). nil-safe.
func WithWebSearchPlatform ¶
func WithWebSearchPlatform(p component.PlatformMeta) WebSearchOption
WithWebSearchPlatform supplies the platform identity used to build observation entity IDs and resolve the calling loop's entity ID. Required when publisher is non-nil; ignored otherwise.
func WithWebSearchTriplePublisher ¶
func WithWebSearchTriplePublisher(p agentictools.TriplePublisher) WebSearchOption
WithWebSearchTriplePublisher enables graph emission. When the publisher is non-nil, each successful search result mints an agent.web.observation entity and writes the per-URL predicates plus a back-link from the calling loop. nil disables emission (default).
Source Files
¶
- bash.go
- flow_lifecycle.go
- flow_templates.go
- flows.go
- graph_query.go
- httprequest.go
- personas.go
- register.go
- register_bash.go
- register_component_catalog.go
- register_decide.go
- register_emit_diagnosis.go
- register_emit_lesson.go
- register_flow_lifecycle.go
- register_flow_monitor.go
- register_flow_templates.go
- register_flows.go
- register_graph_query.go
- register_http_request.go
- register_personas.go
- register_read_loop_result.go
- register_rules.go
- register_scratchpad.go
- register_search_graph.go
- register_summarize_graph.go
- register_web_search.go
- register_write_todos.go
- rules.go
- search_graph.go
- summarize_graph.go
- web_emit.go
- websearch.go
- websearch_stub.go