agent.sh
Repo: github.com/surya-prakash-susarla/agent_sh
Single bash script LLM REPL with tool use (command execution). Dependencies: curl, jq. No daemons, no runtimes, no install — download and run.
Design
- All commands require explicit per-invocation approval before execution
- Multi-turn conversation: full history sent each turn as JSON lines (
.agent_conversation) - Each history entry:
{role, content}— roles: system / user / assistant / tool - Built with bashly:
bashly.yml+build.sh→dist/agentbinary
Source Layout
| File | Role |
|---|---|
src/root_command.sh |
Entry point — resolves config, enters REPL |
src/lib/instructions.sh |
System prompt: tool JSON format, web safety rules |
src/lib/repl.sh |
REPL loop — input, approval gating, history, display |
src/lib/network.sh |
POSTs conversation to endpoint, parses tool calls vs. replies |
src/lib/logging.sh |
Debug output, gated by --debug flag |
Tool Call Protocol
get_response() returns typed JSON:
{ "type": "tool", "assistant_message": { ... }, "command": "git log -n 5 --oneline" }
type: tool→ print[Tool Request], prompt approval, run command, appendtoolmessage to history, looptype: assistant→ print reply, exit tool loop
Without this typed return, the loop would re-run the same command on multi-step flows.
Web Fetch Rules (in system prompt)
- Always
-s --failwith explicit timeouts - Prefer plain text / JSON endpoints (DuckDuckGo Lite, Wikipedia API)
- No binary downloads unless explicitly requested by user
- Summarize result + cite URL; report failures, don't retry blindly
Tests
Scripts in tests/, driven by env vars:
export AGENT_ENDPOINT="http://your-llm:11434"
export AGENT_MODEL="your-model"
bash run_tests.sh
test_conversation.sh— chat continuity and memorytest_tool_use.sh— command execution and approval flowtest_simple_denial.sh,test_multi_denial.sh,test_recursive_approval.sh— denial/approval edge cases
Logs: outputs/*.log
Release
dist/agent binary versioned in git. MIT licensed. v1.0.0 available as a downloadable asset.