A Docker image that runs an SSH-backed Linux terminal with an AI agent, exposed via A2A
946
A Docker image that runs an SSH-backed Linux terminal with an AI agent, exposed via A2A and OpenAI-compatible HTTPS APIs, and a browser-accessible xterm.js terminal UI.
Implements an agent using the ReAct (Reasoning + Acting) pattern for intelligent terminal orchestration.
The container bundles:
https://localhost/The agent runs shell commands, reads/writes files, and inspects system state — repeating until the task is complete or the step budget is exhausted.
| Feature | Details |
|---|---|
| Browser terminal | xterm.js UI with WebSocket PTY relay to SSH — full ANSI/color support |
| Shell automation | AI agent executes shell commands via SSH to complete tasks |
| LLM-driven agent | Any OpenAI-compatible LLM (GPT-4o, Claude, Gemini, local models) |
| Loop detection | Warns the LLM after 2 consecutive identical actions |
| A2A API | Google Agent-to-Agent JSON-RPC 2.0 protocol |
| OpenAI-compatible API | /v1/chat/completions endpoint — drop-in for OpenAI clients |
| HTTPS | Self-signed TLS certificate generated at startup |
cd apps/linux_terminal_agent
docker build --build-context a2a_pkg=../../packages/a2a_agent -f Dockerfile.ubuntu -t linux_terminal_agent:ubuntu .
docker run -d \
--name terminal_agent \
-p 443:443 \
-p 2222:22 \
-e LLM_URL=https://api.openai.com/v1 \
-e LLM_API_KEY=sk-... \
-e LLM_MODEL=gpt-4o \
linux_terminal_agent:ubuntu
| Service | URL / Address |
|---|---|
| Browser terminal | https://localhost/ |
| Agent API (A2A + OpenAI) | https://localhost/ |
| SSH (direct) | ssh root@localhost -p 2222 (password: agent) |
The container generates a local CA on first start. Install it once and your browser will trust all future connections without warnings.
macOS:
curl -k https://localhost/ca.crt -o linux-terminal-agent-ca.crt
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain linux-terminal-agent-ca.crt
Linux (Debian/Ubuntu):
curl -k https://localhost/ca.crt -o /usr/local/share/ca-certificates/linux-terminal-agent-ca.crt
sudo update-ca-certificates
Windows:
curl -k https://localhost/ca.crt -o linux-terminal-agent-ca.crt
certutil -addstore Root linux-terminal-agent-ca.crt
Chrome / Firefox (manual): download https://localhost/ca.crt then add it in
Settings → Privacy and security → Manage certificates → Authorities → Import.
curl -sk -X POST https://localhost/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "tasks/send",
"params": {
"id": "task-1",
"message": {
"role": "user",
"parts": [{"text": "List the files in /etc and tell me the OS version"}]
}
}
}'
curl -sk -X POST https://localhost/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "terminal-agent",
"messages": [{"role": "user", "content": "What OS is this and how much disk space is free?"}]
}'
curl -sk https://localhost/.well-known/agent.json
curl -sk -N -X POST https://localhost/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "tasks/sendSubscribe",
"params": {
"message": {
"role": "user",
"parts": [{"text": "Find all Python files larger than 100KB"}]
}
}
}'
| Variable | Default | Description |
|---|---|---|
LLM_URL | https://api.openai.com/v1 | Base URL of the LLM API |
LLM_API_KEY | — | API key for the LLM |
LLM_MODEL | gpt-4o | Model name |
SSH_HOST | localhost | SSH server host for agent tools |
SSH_PORT | 22 | SSH server port |
SSH_USER | root | SSH username |
SSH_PASSWORD | — | SSH password |
SSH_KEY_PATH | — | Path to SSH private key file (alternative to password) |
API_KEY | — | Bearer token to protect the agent API (optional) |
PORT | 443 | HTTPS port for the agent server |
AGENT_URL | — | Public URL published in the AgentCard (e.g. https://my-agent.example.com/). Defaults to https://localhost:{PORT}/ |
| Variable | Default | Description |
|---|---|---|
TRAJECTORY_DIR | — | Directory to save trajectory data; each run creates a YYYYMMDD_HHMMSS/ subdirectory |
When TRAJECTORY_DIR is set, each agent run creates a timestamped subdirectory containing one folder per step:
$TRAJECTORY_DIR/
20260304_181523/ # run timestamp (YYYYMMDD_HHMMSS)
turn_0000/
llm_0_request.json # task, step, model, full message history sent to LLM
llm_0_response.json # raw reply, parsed action/args/reasoning, token usage
command.json # action, args, shell output, duration_ms
turn_0001/
...
20260304_182041/ # next run
...
Example:
docker run -d \
-e LLM_URL=... -e LLM_API_KEY=... \
-e TRAJECTORY_DIR=/data/traj \
-v /tmp/agent-traj:/data/traj \
linux_terminal_agent:ubuntu
| Tool | Description |
|---|---|
run_command | Run a shell command, return stdout/stderr/exit_code |
list_processes | List running processes (ps aux) |
kill_process | Send a signal to a process |
get_system_info | uname, CPU, memory, and disk summary |
list_dir | List directory contents (ls -la) |
read_file | Read a file (up to max_bytes) |
write_file | Write content to a file |
patch_file | Apply a unified diff to a file |
grep_text | Search files for a pattern (ripgrep / grep fallback) |
http_request | Make an HTTP request via curl |
tail_file | Return the last N lines of a file |
get_resource_usage | CPU/memory/disk/GPU usage snapshot |
┌──────────────────────────────────────────────┐
│ Docker Container │
│ │
│ OpenSSH server (:22) │
│ │ │
│ ├── xterm.js PTY relay │
│ │ (WebSocket /ws/terminal) │
│ │ │
│ └── Agent tool calls │
│ (run_command, read_file, ...) │
│ │
│ LangGraph (graph.py) │
│ call_llm ──► LLM (OpenAI-compatible) │
│ execute_action │
│ │
│ FastAPI Server (:443 HTTPS) │
│ ├── GET / xterm.js UI │
│ ├── GET /ws/terminal PTY WebSocket │
│ ├── POST / A2A JSON-RPC │
│ └── POST /v1/... OpenAI-compat │
└──────────────────────────────────────────────┘
MIT
The agent image exposes an MCP (Model Context Protocol) server on the same port as A2A at /mcp. Any MCP client — Claude Desktop, Cursor, Windsurf, ChatGPT Connectors, OpenAI Agents SDK — can list and invoke these tools using the pod's API_KEY as Bearer.
In production, Core proxies https://linux-terminal-agent.agents.forfetch.ai/mcp → the worker pod's /mcp.
| Tool (skill_id) | Description |
|---|---|
run_command | Execute a shell command |
write_file | Write content to a file |
read_file | Read content from a file |
list_dir | List directory contents |
install_package | Install a system or language package |
Input schemas are authored in apps/agents_mcp/app/seed.py. Skills without an explicit schema advertise a single {task: str} freeform parameter.
Content type
Image
Digest
sha256:ae8de3137…
Size
251.1 MB
Last updated
5 months ago
docker pull superbizon007/linux-terminal-agent