Skip to content

v0.3: Commands, Logs, And Approvals [CORE COMPLETED]

Implementation Status

First slice shipped in 3708d7e:

  • Added backend/agent/g_agent/command/ with shared CommandRouter, CommandContext, and built-in handlers.
  • Wired chat slash commands and direct CLI agent mode through the same command dispatcher for the implemented command set.
  • Added shared quoted-argument parsing and helpful unknown-command responses.
  • Added /logs backed by task checkpoints with bounded output and obvious secret redaction.
  • Added /sessions and /history on top of the v0.2 SQLite session store.
  • Added /approve pass-through so AgentLoop can replay pending approvals with the live tool registry, and /deny to clear pending approvals for the current session.
  • Added tests in test_slash_command_router.py.

Additional shipped slice:

  • Added security/approval_state.py with persisted append-only approval state under workspace/state/approvals.jsonl.
  • Pending approvals now receive ids that survive process restarts.
  • /deny updates persisted approval state when denying id-backed pending approvals.
  • Added /approvals to list current-session pending approval ids.
  • Added test_approval_state.py.
  • Added security/approval_policy.py with deterministic risky shell and filesystem classifier examples.
  • AgentLoop now applies the classifier under approvalMode=confirm even when a tool is not explicitly listed in tools.riskyTools.
  • Added test_approval_policy.py.
  • Added /approve session <tool> and /approve always <tool> for narrow session-scoped tool allowlists backed by approval state.
  • Added /approvals clear <id> and /approvals clear all to remove pending or allowlisted approval records for the current session.
  • Pending approval replay remains approve-once: replayed entries are removed from session metadata and marked executed in approval state.

Remaining follow-up:

  • Move more legacy handlers from channels/slash_commands.py into command/builtin.py once behavior parity is locked.

Goal

Make the owner able to control the agent from chat, CLI, and later Web UI.

User Outcome

Commands behave the same across surfaces. Risky actions pause for approval instead of failing mysteriously or requiring broad permissions.

Scope

  • Normalize slash commands across WhatsApp, Telegram, Discord, CLI, and Web UI.
  • Add a shared command router.
  • Add recent log inspection from CLI and chat.
  • Add dangerous action detection for shell and filesystem tools.
  • Track pending approvals per session/chat.
  • Let owners approve once, deny, or add a narrow persistent allowlist.
  • Surface blocked-command reasons clearly in chat and logs.
  • Avoid broad auto-approval until policy is tested.

Minimum Commands

  • /status
  • /logs
  • /new
  • /stop
  • /restart
  • /whoami
  • /sessions
  • /search
  • /approve
  • /deny
  • /tools
  • /memory
  • /skills

Module Targets

  • backend/agent/g_agent/command/router.py
  • backend/agent/g_agent/command/builtin.py
  • backend/agent/g_agent/agent/tools/approval.py
  • backend/agent/g_agent/security/approval_policy.py
  • backend/agent/g_agent/observability/log_reader.py
  • backend/agent/g_agent/channels/
  • backend/agent/tests/test_command_router.py
  • backend/agent/tests/test_approval_policy.py

Acceptance Criteria

  • Commands parse consistently across CLI and at least one chat channel.
  • Unknown commands return helpful responses.
  • Risky actions create pending approval records.
  • /approve resumes or replays the blocked action where possible.
  • /deny records the decision and instructs the agent to continue safely.
  • Logs command truncates output and redacts obvious secrets.

Tests

  • Command parser handles args, quoted strings, and unknown commands.
  • Approval policy classifies risky shell/file examples.
  • Pending approvals are scoped by session/chat.
  • Denied actions do not execute.
  • Log output is bounded.

References

  • hermes-agent-ref/tools/approval.py
  • hermes-agent-ref/agent/skill_commands.py

Agent Handoff

Current G-Agent State

  • channels/slash_commands.py is the current command dispatcher. Do not create a parallel command system; extend the existing dispatcher and g_agent.command wrapper.
  • Existing commands include /new, /reset, /compact, /context, /status, /whoami, /memory, /model, /tools, /cron, /packs, /search, /history, /sessions, /logs, /approve, /deny, /help, and /commands.
  • AgentLoop already has tool_policy, risky_tools, approval_mode, and _execute_tool_with_policy.
  • User-facing approval flow has first-class /approve pass-through, /deny session-metadata clearing, persisted approval state, and /approvals listing. It still needs richer denied-replay coverage and command-router extraction for the remaining legacy handlers.
  • Runtime checkpoints already track running tasks and events in agent/runtime.py; /logs reads them with bounded output and obvious secret redaction. /status enrichment remains follow-up work.

Reference Details To Inspect

  • hermes-agent-ref/tools/approval.py
  • context-local session key
  • pending approval queue per session
  • approve once/session/always/deny
  • permanent allowlist
  • cron unattended denial
  • gateway notification callback
  • nanobot-ref/nanobot/command/router.py
  • shared command router shape.
  • nanobot-ref/nanobot/command/builtin.py
  • built-in command organization.

Implementation Strategy

Start by extracting the existing dispatcher into a package, but keep imports compatible.

Recommended shape:

  • command/router.py: parse command and route to handlers.
  • command/context.py: command context with channel, chat id, session key, sender id, workspace, model, services.
  • command/builtin.py: handlers currently living in SlashCommandDispatcher.
  • channels/slash_commands.py: compatibility wrapper that delegates to new router.
  • security/approval_state.py: persisted pending approvals.
  • security/approval_policy.py: classify risky commands/tool calls.

Implementation Slices

  1. Add command context and parser tests.
  2. Preserve existing command behavior exactly.
  3. Move handlers gradually.
  4. First move /status, /context, /commands, /help.
  5. Then move session commands.
  6. Then move memory/model/tools/cron/packs.
  7. Add /logs.
  8. Read latest task checkpoint files from workspace/state/tasks.
  9. Include failed tool calls and provider errors when available.
  10. Keep output bounded.
  11. Add approval state.
  12. Persist under workspace/state/approvals.jsonl or SQLite once v0.2 exists.
  13. Fields: id, session_key, channel, chat_id, sender_id, tool_name, arguments, reason, created_at, status.
  14. Add /approve and /deny.
  15. /approve approves the oldest pending item for current session.
  16. /approve all approves all current-session pending items.
  17. /deny denies oldest.
  18. Return clear text when nothing is pending.
  19. Integrate with AgentLoop._execute_tool_with_policy.
  20. When blocked, record pending approval and return a tool result that tells the model not to retry blindly.

Tests To Add

  • test_command_router.py
  • unknown command behavior
  • aliases
  • quoted args
  • HTML escaping where needed
  • test_logs_command.py
  • reads checkpoint failures
  • truncates long data
  • test_approval_state.py
  • create/list/approve/deny pending approvals
  • session scoping
  • approve all
  • test_agent_tool_approval.py
  • risky tool creates pending approval
  • deny does not execute
  • approved once executes once

Compatibility Rules

  • Keep /search web search behavior unless intentionally migrated in a release note.
  • Keep /new and /compact behavior from existing tests.
  • Do not auto-approve shell commands from natural language.
  • Do not store secrets in approval payload previews.

First PR Boundary

Extract command router + add /logs + add approval state storage without rewiring all tools. Second PR wires approval state into tool execution.