Documentation
¶
Overview ¶
Package hitlservice evaluates approval policies for tool calls. Policy decisions (allow / deny / approve) are returned to the caller; the caller (typically a ToolsRepo decorator like localtools.HITLWrapper) is responsible for actually pausing execution and sourcing the human decision.
Index ¶
Constants ¶
const ( ReasonMatchedRule = "matched_rule" ReasonDefaultAction = "default_action" )
Reason constants used in EvaluationResult.Reason.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Action ¶
type Action string
Action is the outcome of policy evaluation for a tool call.
const ( // ActionAllow passes the tool call through without any approval step. ActionAllow Action = "allow" // ActionApprove blocks execution and requests human approval before proceeding. ActionApprove Action = "approve" // ActionDeny rejects the tool call immediately with a soft message to the LLM. ActionDeny Action = "deny" )
type ApprovalRequest ¶
type ApprovalRequest struct {
ToolCallID string
ToolsName string
ToolName string
Args map[string]any
Diff string
DiffOld string
DiffNew string
}
ApprovalRequest describes a tool invocation that requires human review. Diff is populated for file-mutation tools (write_file, sed) to show the unified diff of what would change.
type Condition ¶
type Condition struct {
Key string `json:"key"`
Op ConditionOp `json:"op"`
Value string `json:"value"`
}
Condition is a single key/op/value predicate applied to the args of a tool call.
type ConditionOp ¶
type ConditionOp string
ConditionOp is the comparison operator for a rule condition.
const ( // OpEq requires the argument value to equal the condition value exactly. OpEq ConditionOp = "eq" // OpGlob matches the argument value against a glob pattern. // Both value and pattern are normalized with path.Clean before matching, // preventing path-traversal bypass (e.g. ./src/../etc/passwd → etc/passwd). // Supports * (within a path component), ? (single char), and ** (across separators). OpGlob ConditionOp = "glob" // OpHost treats the argument value as a URL and matches its host against a // comma-separated list of host patterns in Value. It is the policy-native // way to express SSRF-style host denial (e.g. webtools to localhost or a // cloud-metadata endpoint): the host is parsed out of the URL, so a trailing // :port or path cannot evade the match the way a raw URL glob can. IP // literals match exactly; bare names match the host and any subdomain // (api.example.com matches example.com). OpHost ConditionOp = "host" // OpCommandBlacklist matches the command basename against a comma-separated // list of denied commands. Used to block dangerous commands like rm, sudo, dd. OpCommandBlacklist ConditionOp = "command_blacklist" // OpCommandAskAlways matches the command basename against a comma-separated // list of commands that should always require human approval (e.g., rm, sudo, chmod). // Unlike OpCommandBlacklist which denies, this operator with action:"approve" creates // a HITL pause point for safety-critical commands. OpCommandAskAlways ConditionOp = "command_ask_always" // OpNoCommandSubstitution blocks commands containing shell substitution // patterns ($(), backticks, <(), >()) that could indicate command injection. OpNoCommandSubstitution ConditionOp = "no_command_substitution" )
type EvaluationResult ¶
type EvaluationResult struct {
Action Action
MatchedRule *int // nil when DefaultAction was applied (no rule matched)
Reason string // ReasonMatchedRule or ReasonDefaultAction
TimeoutS int
OnTimeout Action
}
EvaluationResult carries the policy decision plus introspection data.
type Policy ¶
type Policy struct {
DefaultAction Action `json:"default_action,omitempty"`
Rules []Rule `json:"rules"`
}
Policy is the top-level document stored as hitl-policy.json in the VFS. Rules are evaluated in order; the first matching rule wins. DefaultAction is applied when no rule matches; it is fail-closed to "approve" when absent so an unaccounted-for tool pauses for a human.
type PolicyEvaluator ¶
type PolicySource ¶
type PolicySource interface {
ReadPolicy(ctx context.Context, tenantID, name string) ([]byte, error)
}
PolicySource reads a named HITL policy document for a tenant. Any error (including not-found) makes the evaluator fall back to the built-in default policy, so implementations need not special-case absence.
func NewFSPolicySource ¶
func NewFSPolicySource(dirs ...string) PolicySource
NewFSPolicySource returns a PolicySource that looks up "<dir>/<name>" in each dir in order, returning the first hit. tenantID is ignored: the OSS runtime is single-tenant. Empty dirs are skipped. Tenant-scoped builds inject their own PolicySource (e.g. backed by the VFS) instead.
type Rule ¶
type Rule struct {
Tools string `json:"tools"`
Tool string `json:"tool"`
When []Condition `json:"when,omitempty"`
Action Action `json:"action"`
// TimeoutS is the number of seconds to wait for a human response when Action is
// ActionApprove. Zero means no timeout (block indefinitely until ctx is cancelled).
TimeoutS int `json:"timeout_s,omitempty"`
// OnTimeout is the fallback action when the approval window expires.
// Only "deny" and "approve" are valid (allow would silently bypass approval).
OnTimeout Action `json:"on_timeout,omitempty"`
}
Rule matches a tools+tool pair (with optional conditions) and assigns an action. When contains zero conditions the name match alone is sufficient. All conditions in When must hold for the rule to match (AND semantics).
type Service ¶
type Service interface {
PolicyEvaluator
RequestApproval(ctx context.Context, req ApprovalRequest, sink taskengine.TaskEventSink) (bool, error)
Respond(approvalID string, approved bool) bool
}
func New ¶
func New(src PolicySource, tenantID string, store KVReader, tracker libtracker.ActivityTracker) Service
New constructs a hitlservice bound to a tenant. The tenantID is forwarded to every policy lookup the service performs.
func NewWithDefaultPolicy ¶
func NewWithDefaultPolicy(src PolicySource, tenantID string, store KVReader, tracker libtracker.ActivityTracker, fallbackPolicy string) Service