AgentGuard connects to DSH's native tools/pre-execute and tools/post-execute waterfalls. It translates each non-AgentGuard tool call into the shared RuntimeAction vocabulary, resolves the same effective policy used by the other AgentGuard hosts, runs the shared OSS evaluator, and writes a local audit event.
The runtime integration accepts three explicit modes:
| Mode | Pre-execute | Post-execute | Intended use |
|---|---|---|---|
off |
no listener | no listener | scanner tools only |
observe |
evaluate and audit; preserve downstream decision | evaluate network responses and audit | packaged default and rollout baseline |
protect |
apply allow, warn, native ask, or deny |
audit by default; optionally suppress block-class malicious results | explicit real-time protection |
The npm bundle continues to compose observe by default so installing an update does not silently change tool execution. Enable protection in a custom DSH composition:
- insert:
- id: agentguard-dsh-plugin
name: '@goplus/agentguard/dist/dsh/plugin.js'
config:
runtime:
mode: protect
failureMode: deny
unknownToolDecision: ask
postResponseMode: block-malicious
attribution:
toolOwners:
find_dsh_plugin: dsh-find-plugin
ownerPolicies:
dsh-find-plugin:
minimumDecision: require_approvalfailureMode applies only to unexpected evaluator failures in protect mode. It defaults to deny. Set it to allow only for a deliberate compatibility rollout. Audit-file write failures do not erase a successfully evaluated policy decision and do not disable enforcement.
At plugin startup AgentGuard logs the configured mode and whether pre-execute enforcement is active. agentguard_dsh_runtime_summary also returns configuredMode, preExecuteProtectionActive, and configuredPostResponseMode even when the audit log is empty. Historical runtimeModes counts describe observed events; they are not a substitute for the current configured mode.
- DSH supplies the immutable tool name, parsed arguments, call identity, root-call identity, optional parent token, and calling agent.
- AgentGuard uses the official session header for the workspace cwd and resolves a relative shell workdir against it.
- Common command, patch, image, file-search, HTTP, browser, deployment, skill-install, and MCP tools map to the shared action types. Skill-install and MCP actions require approval by the default runtime policy. Unknown tools remain
other; inprotectthey default to nativeaskand can be configured withunknownToolDecision: ask|deny|allow. - Network method, headers, and bounded body context are preserved for the shared evaluator.
- AgentGuard resolves Cloud, cached, or bundled-default policy and evaluates locally. Cloud failure falls back to cached/default policy.
- In
observe, the downstream DSH policy is returned unchanged. Inprotect, the AgentGuard result is translated and monotonically merged with the downstream policy so a stronger third-partyaskordenyis never weakened. A final AgentGuarddenyshort-circuits the pre-execute waterfall and does not dispatch the downstream tool body. - AgentGuard's own
agentguard_*tools are excluded to prevent recursive protection.
| AgentGuard decision | DSH pre-execute result | Behavior |
|---|---|---|
allow |
allow |
execute |
warn |
allow |
execute and retain warning in audit |
require_approval |
ask |
use DSH's native approval service |
block |
deny |
do not dispatch the tool body |
DSH owns the one-shot approval interaction and its durable approval/asked plus approval/decided pair. AgentGuard does not create a parallel CLI approval entry. Only allowed-once resumes that tool call; rejection, cancellation, missing approval channels, headless never, a missing approval service, and agent-less calls fail closed in DSH.
The reason passed into DSH contains only a bounded risk score, normalized policy metadata, and up to five reason codes. Raw tool input, detector descriptions, evidence, and untrusted control text are excluded.
Network results pass through tools/post-execute. AgentGuard extracts a bounded response preview plus available status, content type, headers, and byte count, then evaluates response and network-volume anomalies.
Post-execute remains audit-only in observe and in the default protect configuration. Set postResponseMode: block-malicious together with mode: protect to suppress only results whose final AgentGuard post-execute decision is block. The original result value and rendered content are not returned; DSH receives bounded AgentGuard feedback that excludes the untrusted preview and evidence. A stronger downstream block is preserved.
Approval-class post results remain audit-only because DSH has no native post-result ask or resumable held-result carrier. AgentGuard records the remaining native-post-result-approval and approved-result-resume gates rather than destroying a result that could not be resumed. Unexpected post evaluator errors fail open for the result path and remain available to downstream DSH policies; this avoids irrecoverable response loss caused by an internal guard failure.
Events are written to ~/.agentguard/audit.jsonl with:
- native call/root identities and nested-call state;
- verified invocation context (
model-directornested-tool), top-level/subagent origin, delegation depth, and agent preset when DSH supplies them; sourceAttribution: "configured-tool-owner"plussourceOwnerfor exact operator-configured tool ownership bindings;- shared decision, risk score, risk level, reason codes, and policy version;
runtimeMode,runtimePhase, andenforcementApplied;- the translated hook decision and disposition;
sourceAttribution: "unknown"when no reliable owner binding exists.
runtime.attribution.toolOwners is an exact, case-sensitive map from a DSH tool name to a stable plugin or package id. It is operator-authored trust metadata, not a tool-name heuristic. Owner ids are bounded and validated, duplicate/ambiguous wildcard matching is not supported, and an unmapped tool remains unknown. Do not bind a name when another agent scope may shadow it with a different implementation.
runtime.ownerPolicies applies only after a call has a matching configured-tool-owner. Each owner declares a minimumDecision of allow, warn, require_approval, or block. This is a monotonic floor: it can strengthen the shared AgentGuard decision but can never weaken it. In particular, minimumDecision: allow means “no additional owner restriction”; it does not bypass a warning, approval, or block produced by the shared policy. An elevation adds the bounded DSH_OWNER_POLICY reason code to audit and native approval text.
In protect, pre-execute events set enforcementApplied: true and record the applied DSH hook decision. With postResponseMode: block-malicious, block-class post-execute events also set it to true and record hookDecisionApplied: block; approval-class post events remain false. DSH session events are the source of truth for the final human approval outcome.
agentguard_dsh_runtime_summary reads only the bounded final 1 MiB of the audit log and aggregates up to 1,000 recent DSH events. It reports decisions, action types, risks, phases, modes, applied-enforcement count, dispositions, gates, reason-code counts, nested calls, attribution coverage, invocation sources, session origins, and the top configured owners. Raw tool inputs and reason evidence are never returned to the model. An exact optional sessionId filter isolates one DSH call tree.
DSH does not maintain a separate detector. The normalized action goes through AgentGuard's shared policy and evaluator, so dangerous commands, protected paths, credential access, data exfiltration, outbound-network policy, response anomalies, and remote code execution retain the same semantics as other hosts.
Direct unpinned Git package execution through npx, npm exec, pnpm dlx, yarn dlx, or bunx requires approval. A full 40-character commit pin reduces this to a warning rather than treating remote code as trusted.
The host-parity matrix requires equivalent shell, file, and network actions to produce identical decisions, risk scores, risk levels, and reason codes across DSH, Codex, Claude Code, and OpenClaw. Host-specific lifecycle behavior is tested separately.
The real DSH ToolRuntime, ApprovalService, and Session tests cover:
- concurrent safe calls;
- pre-execute allow, warn, native approval, rejection, and block;
- shell, file-write, and network actions;
- root and nested calls without duplicate approval;
- cancellation, unavailable/headless approval, missing services, and missing agents;
- stronger downstream policies;
- fail-closed and explicit fail-open evaluator errors;
- bounded audit output and explicit unknown attribution;
- audit-only approval-class response handling and optional block-class response suppression;
- plugin disposal removing the policy listener;
- install, update, uninstall, packaged assets, and live HTTP startup.
DSH currently supplies no reliable source-plugin ownership field on the lifecycle event. AgentGuard therefore supports exact operator-configured bindings and otherwise records explicit unknown attribution rather than guessing. Plugin-specific trust cannot silently bypass policy. When DSH exposes a stable tool-owner/provider identity, it can supersede configured bindings without changing the shared evaluator.