Documentation
¶
Overview ¶
Package executors provides tool executor implementations for the agentic system.
BashExecutor runs shell commands. When a sandbox is configured (SANDBOX_URL), commands execute inside the sandbox container. Otherwise, they run locally via os/exec with sensitive environment variables stripped.
Ported from semspec/tools/bash.
Package executors provides tool executor implementations for the agentic-tools component.
Package executors provides tool executor implementations for the agentic-tools component.
Package executors hosts the concrete tool implementations and their wire-to-global-registry entry points.
Stateless tools (bash, http_request, web_search, github_*) 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 RegisterAll is main.go, after ensureStreams and before component.Start. Keeping wiring out of agentic-tools.Component leaves that component a pure tool-execution endpoint (it reads from the global registry, it doesn't write to it).
Index ¶
- Variables
- func RegisterAll(ctx context.Context, deps ToolDependencies)
- type BashExecutor
- type BashOption
- type FlowExecutor
- type FlowManager
- type FlowTemplateExecutor
- type FlowTemplateManager
- type GitHubClient
- type GitHubHTTPClient
- func (c *GitHubHTTPClient) AddComment(ctx context.Context, owner, repo string, number int, body string) error
- func (c *GitHubHTTPClient) AddLabels(ctx context.Context, owner, repo string, number int, labels []string) error
- func (c *GitHubHTTPClient) CommitFile(ctx context.Context, owner, repo, branch, path, content, message string) error
- func (c *GitHubHTTPClient) CreateBranch(ctx context.Context, owner, repo, branch, baseSHA string) error
- func (c *GitHubHTTPClient) CreatePullRequest(ctx context.Context, owner, repo, title, body, head, base string) (*GitHubPR, error)
- func (c *GitHubHTTPClient) GetFileContent(ctx context.Context, owner, repo, path, ref string) (string, error)
- func (c *GitHubHTTPClient) GetIssue(ctx context.Context, owner, repo string, number int) (*GitHubIssue, error)
- func (c *GitHubHTTPClient) GetPullRequest(ctx context.Context, owner, repo string, number int) (*GitHubPR, error)
- func (c *GitHubHTTPClient) ListIssues(ctx context.Context, owner, repo string, opts ListIssuesOpts) ([]GitHubIssue, error)
- func (c *GitHubHTTPClient) SearchIssues(ctx context.Context, query string) ([]GitHubIssue, error)
- type GitHubIssue
- type GitHubPR
- type GitHubReadExecutor
- type GitHubWriteExecutor
- type GraphQueryExecutor
- type HTTPRequestExecutor
- type HTTPRequestOption
- type JetStreamKVAdapter
- type KVEntry
- type KVGetter
- type ListIssuesOpts
- type PersonaExecutor
- type PersonaManager
- type RuleExecutor
- type RuleManager
- type StubWebSearchExecutor
- type ToolDependencies
- type WebSearchExecutor
Constants ¶
This section is empty.
Variables ¶
var ErrKeyNotFound = errs.ErrKeyNotFound
ErrKeyNotFound is returned when a key is not found in the KV store.
Functions ¶
func RegisterAll ¶
func RegisterAll(ctx context.Context, deps ToolDependencies)
RegisterAll wires every tool this package owns into the agentic-tools global registry. Failures are logged; stateful-tool wiring that can't reach its bucket skips silently and lets the rest proceed — same philosophy as the pre-refactor init() pattern.
Types ¶
type BashExecutor ¶
type BashExecutor struct {
// contains filtered or unexported fields
}
BashExecutor runs shell commands locally or via sandbox.
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.
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.
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).
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 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 GitHubClient ¶
type GitHubClient interface {
GetIssue(ctx context.Context, owner, repo string, number int) (*GitHubIssue, error)
ListIssues(ctx context.Context, owner, repo string, opts ListIssuesOpts) ([]GitHubIssue, error)
SearchIssues(ctx context.Context, query string) ([]GitHubIssue, error)
GetPullRequest(ctx context.Context, owner, repo string, number int) (*GitHubPR, error)
GetFileContent(ctx context.Context, owner, repo, path, ref string) (string, error)
CreateBranch(ctx context.Context, owner, repo, branch, baseSHA string) error
CommitFile(ctx context.Context, owner, repo, branch, path, content, message string) error
CreatePullRequest(ctx context.Context, owner, repo, title, body, head, base string) (*GitHubPR, error)
AddComment(ctx context.Context, owner, repo string, number int, body string) error
AddLabels(ctx context.Context, owner, repo string, number int, labels []string) error
}
GitHubClient defines the interface for GitHub API operations. All methods accept context for cancellation and timeout propagation.
type GitHubHTTPClient ¶
type GitHubHTTPClient struct {
// contains filtered or unexported fields
}
GitHubHTTPClient implements GitHubClient using the GitHub REST API v3. It authenticates via a Bearer token and parses only the fields the system needs.
func NewGitHubHTTPClient ¶
func NewGitHubHTTPClient(token string) *GitHubHTTPClient
NewGitHubHTTPClient creates a new GitHubHTTPClient with the given personal access token.
func (*GitHubHTTPClient) AddComment ¶
func (c *GitHubHTTPClient) AddComment(ctx context.Context, owner, repo string, number int, body string) error
AddComment posts a comment on an issue or pull request.
func (*GitHubHTTPClient) AddLabels ¶
func (c *GitHubHTTPClient) AddLabels(ctx context.Context, owner, repo string, number int, labels []string) error
AddLabels applies labels to an issue or pull request.
func (*GitHubHTTPClient) CommitFile ¶
func (c *GitHubHTTPClient) CommitFile(ctx context.Context, owner, repo, branch, path, content, message string) error
CommitFile creates or updates a single file on a branch using the Contents API. content is the raw file text; this method handles base64 encoding.
func (*GitHubHTTPClient) CreateBranch ¶
func (c *GitHubHTTPClient) CreateBranch(ctx context.Context, owner, repo, branch, baseSHA string) error
CreateBranch creates a new branch from the given base SHA. It uses the Git refs API rather than the higher-level branch API so the caller controls exactly which commit the branch points at.
func (*GitHubHTTPClient) CreatePullRequest ¶
func (c *GitHubHTTPClient) CreatePullRequest(ctx context.Context, owner, repo, title, body, head, base string) (*GitHubPR, error)
CreatePullRequest opens a new pull request from head into base.
func (*GitHubHTTPClient) GetFileContent ¶
func (c *GitHubHTTPClient) GetFileContent(ctx context.Context, owner, repo, path, ref string) (string, error)
GetFileContent retrieves the decoded text content of a file at a specific ref.
func (*GitHubHTTPClient) GetIssue ¶
func (c *GitHubHTTPClient) GetIssue(ctx context.Context, owner, repo string, number int) (*GitHubIssue, error)
GetIssue fetches a single issue by number.
func (*GitHubHTTPClient) GetPullRequest ¶
func (c *GitHubHTTPClient) GetPullRequest(ctx context.Context, owner, repo string, number int) (*GitHubPR, error)
GetPullRequest fetches a single pull request by number.
func (*GitHubHTTPClient) ListIssues ¶
func (c *GitHubHTTPClient) ListIssues(ctx context.Context, owner, repo string, opts ListIssuesOpts) ([]GitHubIssue, error)
ListIssues returns a list of issues for a repository filtered by opts.
func (*GitHubHTTPClient) SearchIssues ¶
func (c *GitHubHTTPClient) SearchIssues(ctx context.Context, query string) ([]GitHubIssue, error)
SearchIssues executes a GitHub issue search query.
type GitHubIssue ¶
type GitHubIssue struct {
Number int `json:"number"`
Title string `json:"title"`
Body string `json:"body"`
State string `json:"state"`
Labels []string `json:"labels"`
Assignee string `json:"assignee,omitempty"`
Author string `json:"author"`
HTMLURL string `json:"html_url"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Comments int `json:"comments"`
}
GitHubIssue represents a GitHub issue with the fields relevant to the agentic system.
type GitHubPR ¶
type GitHubPR struct {
Number int `json:"number"`
Title string `json:"title"`
Body string `json:"body"`
State string `json:"state"`
HTMLURL string `json:"html_url"`
Head string `json:"head"`
Base string `json:"base"`
Mergeable *bool `json:"mergeable,omitempty"`
Additions int `json:"additions"`
Deletions int `json:"deletions"`
DiffURL string `json:"diff_url"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
GitHubPR represents a GitHub pull request with the fields relevant to the agentic system.
type GitHubReadExecutor ¶
type GitHubReadExecutor struct {
// contains filtered or unexported fields
}
GitHubReadExecutor provides read-only GitHub tools to agentic agents. It fetches issues, pull requests, and file content without mutating any state.
func NewGitHubReadExecutor ¶
func NewGitHubReadExecutor(client GitHubClient) *GitHubReadExecutor
NewGitHubReadExecutor creates a new GitHubReadExecutor backed by the given client.
func (*GitHubReadExecutor) Execute ¶
func (e *GitHubReadExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute dispatches the tool call to the appropriate handler.
func (*GitHubReadExecutor) ListTools ¶
func (e *GitHubReadExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the tool definitions provided by this executor.
type GitHubWriteExecutor ¶
type GitHubWriteExecutor struct {
// contains filtered or unexported fields
}
GitHubWriteExecutor provides write tools that let agentic agents mutate GitHub state. Operations include branch creation, file commits, PR creation, comments, and labels.
func NewGitHubWriteExecutor ¶
func NewGitHubWriteExecutor(client GitHubClient) *GitHubWriteExecutor
NewGitHubWriteExecutor creates a new GitHubWriteExecutor backed by the given client.
func (*GitHubWriteExecutor) Execute ¶
func (e *GitHubWriteExecutor) Execute(ctx context.Context, call agentic.ToolCall) (agentic.ToolResult, error)
Execute dispatches the tool call to the appropriate handler.
func (*GitHubWriteExecutor) ListTools ¶
func (e *GitHubWriteExecutor) ListTools() []agentic.ToolDefinition
ListTools returns the tool definitions provided by this executor.
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.
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 WithHTTPTimeout ¶
func WithHTTPTimeout(d time.Duration) HTTPRequestOption
WithHTTPTimeout overrides the default request timeout (30s).
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 ListIssuesOpts ¶
type ListIssuesOpts struct {
State string // open, closed, all
Labels []string
Sort string // created, updated, comments
Limit int
}
ListIssuesOpts configures the issue listing query.
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 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 ToolDependencies ¶
type ToolDependencies struct {
NATSClient *natsclient.Client
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
}
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)
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.
func NewWebSearchExecutor ¶
func NewWebSearchExecutor(apiKey string) *WebSearchExecutor
NewWebSearchExecutor creates a web search executor backed by the Brave Search API.
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.
Source Files
¶
- bash.go
- flow_templates.go
- flows.go
- github_client.go
- github_read.go
- github_write.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_flow_monitor.go
- register_flow_templates.go
- register_flows.go
- register_github.go
- register_graph_query.go
- register_http_request.go
- register_personas.go
- register_read_loop_result.go
- register_rules.go
- register_web_search.go
- rules.go
- websearch.go
- websearch_stub.go