Skip to content

feat(gateway): command hooks for deterministic chat commands - #199

Draft
bkuri wants to merge 1 commit into
owainlewis:mainfrom
bkuri:feat/command-hooks
Draft

feat(gateway): command hooks for deterministic chat commands#199
bkuri wants to merge 1 commit into
owainlewis:mainfrom
bkuri:feat/command-hooks

Conversation

@bkuri

@bkuri bkuri commented Sep 8, 2026

Copy link
Copy Markdown

Problem

Every chat message today — including slash commands — costs a full backend turn. Gateway built-ins (/clear, /help, /stop) short-circuit, but anything user-defined has to route through the LLM even when the desired behavior is fully deterministic (e.g. /status running a status script and relaying its output).

Change

Adds a [command_hooks] config table mapping chat slash commands to shell commands, handled in the existing gateway command path before backend dispatch:

  • Reply is the hook's trimmed stdout, relayed verbatim; no agent turn.
  • Message arguments are appended to the command line as trailing positional args (/status agentsstatus-report agents).
  • Failure, empty output, and timeout (>15s) reply with a short deterministic error — a broken hook never silently becomes an LLM turn.
  • Unknown slash commands still reach the backend as before, so backend-side command fallbacks keep working.
  • Hooks run through /bin/sh (POSIX), stdout+stderr captured, kill_on_drop on timeout.

Verification

  • cargo fmt --all --check, cargo clippy --locked --all-targets -- -D warnings, cargo build --locked, cargo test --locked all pass (448 tests).
  • New tests: hook stdout relay + arg passthrough without any backend call; unknown-command fallthrough to the backend; docs build (mkdocs build --strict).

Risk

Low: default config (command_hooks empty) is behavior-identical to today. The command() signature gains async — call site is already async context. Docs updated on the canonical page (docs/reference/cli.md).

Note: the hardened hook runner in #197 (process groups, stdout cap) is a better execution engine for this path; this PR deliberately ships the simpler runner to stay focused, and the two can be unified when #197 lands.

[command_hooks] maps chat slash commands to shell commands whose stdout
is relayed verbatim before any backend dispatch — no agent turn, no
tokens. Message arguments are appended to the command line as trailing
positional arguments. Failing, empty, or timed-out hooks reply with a
short deterministic error and never fall back to the backend; unknown
slash commands still reach the backend unchanged.

Basis for deterministic /status-style commands on chat backends; the
timeout-hook runner from owainlewis#197 can absorb this execution path later.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant