Tool System
Available tools, execution policy, and safety guards.
The agent uses a tool-calling interface to execute shell commands on the host system. Tool definitions and handlers live in internal/agent/tools.go (~435 LOC).
Available Tools
| Tool Name | Alias | Description |
|---|---|---|
bash | run_command | Execute a shell command via bash -lc |
Both names map to the same handler (backward compatibility).
Execution Flow
LLM emits tool_call → Policy Check → Runner → Output → Observation
↓
64KB truncation
+ timeout- Agent runtime extracts tool name and arguments from the LLM response
- Policy check (
internal/agent/policy.go): validates the command - Runner (
internal/executor/runner.go): executes viabash -lc - Output is captured, truncated to 64KB, and wrapped in an observation envelope
- Observation is appended to chat history for the next LLM turn
Command Policy
The current policy is pure pass-through:
- All commands are allowed (no blocklist, no allowlist)
- Only empty commands are blocked
- No sandboxing, chroot, namespace isolation, or seccomp
This is suitable for controlled/authorized environments. Production deployments should implement additional restrictions.
Runner Details
// internal/executor/runner.go
func Run(ctx context.Context, command string, timeout time.Duration) Result- Shell:
bash -lc '<command>' - Default timeout: 60 seconds
- Maximum timeout: 10 minutes
- Output capture: stdout + stderr combined
- Output truncation: 64KB max
- Interactive command heuristic detection
- Exit code captured in result
Observation Schema
Tool results are returned as a structured JSON envelope (schema: z2e.tool_observation.v1):
{
"schema": "z2e.tool_observation.v1",
"timestamp": "2026-05-29T15:48:00Z",
"session": {
"started_at": "...",
"steps": 5,
"executed_commands": 3,
"observations": 3
},
"tool": {
"tool": "bash",
"call_id": "call_xxx",
"command": "nmap -sV example.com",
"workdir": "/home/user",
"raw": "compact(2000 chars)"
},
"result": {
"status": "completed",
"exit_code": 0,
"timed_out": false,
"interactive": false,
"output": "compact(6000 chars)"
}
}The output field is compacted to 6000 characters for the LLM prompt. The raw capture buffer is 64KB.
Safety Guards
Doom-Loop Detection
3 consecutive identical command signatures terminate the agent loop.
Output Overflow
Output beyond 64KB in the raw capture is truncated. The LLM-facing output field is further compacted to 6000 characters.
Timeout Enforcement
Commands exceeding the timeout are killed via context cancellation. The observation includes the partial output captured before termination.
Empty Command Rejection
Empty or whitespace-only commands are rejected at the policy level.