|
| 1 | +# OpenClaw is Now Live on TextAgent 🦀 |
| 2 | + |
| 3 | +**Date**: 2026-03-31 |
| 4 | + |
| 5 | +## What We Shipped |
| 6 | + |
| 7 | +TextAgent's Agent Flow now has native, end-to-end integration with **OpenClaw** — running inside isolated Docker containers with full API key forwarding, multi-step context chaining, and structured JSON response parsing. Write a pipeline in your document, point it at OpenClaw, and execute it locally or in the cloud. |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## How It Works |
| 12 | + |
| 13 | +### The Syntax |
| 14 | + |
| 15 | +In any TextAgent document, drop an Agent Flow block: |
| 16 | + |
| 17 | +```markdown |
| 18 | +{{@Agent: |
| 19 | + @cloud: no |
| 20 | + @agenttype: openclaw |
| 21 | + 1. Research the latest trends in llm compression |
| 22 | + 2. Summarize the findings as a comparison table |
| 23 | + 3. Write a blog post draft from the summary |
| 24 | +}} |
| 25 | +``` |
| 26 | + |
| 27 | +Hit ▶ Run, and TextAgent: |
| 28 | + |
| 29 | +1. **Checks Docker** — if Docker Desktop is running, proceeds immediately |
| 30 | +2. **Builds the OpenClaw image** (first-time only, ~30 seconds) from `agents/openclaw/Dockerfile` using Node.js 22 + `npm install -g openclaw@latest` |
| 31 | +3. **Starts a persistent container** — reused across all steps so you don't pay build cost twice |
| 32 | +4. **Invokes the native OpenClaw CLI** per step: |
| 33 | + ``` |
| 34 | + openclaw agent --session-id textagent-openclaw --local --message "..." --json --timeout 300 |
| 35 | + ``` |
| 36 | +5. **Parses the structured JSON response** — extracts `.reply`, `.text`, `.message`, `.output`, or `.payloads[0].text` depending on what OpenClaw returns |
| 37 | +6. **Chains context** — each step's output is automatically prepended as context for the next step |
| 38 | +7. **Auto-stops the container** after 10 minutes of idle |
| 39 | + |
| 40 | +### Cloud Mode |
| 41 | + |
| 42 | +Flip `@cloud: yes` and the same pipeline runs on a free **GitHub Codespace** — no local Docker required. TextAgent provisions the Codespace via GitHub Device Flow (no backend, OAuth only), forwards your agent steps over `POST /api/exec`, and streams results back in real time. |
| 43 | + |
| 44 | +--- |
| 45 | + |
| 46 | +## What Changed in the Code |
| 47 | + |
| 48 | +### `agent-runner/agents/openclaw/Dockerfile` |
| 49 | +Replaced the Python 3.12 placeholder with a real Node.js 22 image that installs OpenClaw via npm: |
| 50 | + |
| 51 | +```dockerfile |
| 52 | +FROM node:22-slim |
| 53 | +WORKDIR /app |
| 54 | +RUN npm install -g openclaw@latest |
| 55 | +CMD ["tail", "-f", "/dev/null"] |
| 56 | +``` |
| 57 | + |
| 58 | +### `agent-runner/server.js` — `AGENT_CLI_MAP` |
| 59 | + |
| 60 | +The server now has a first-class concept of *known agents* that get native CLI invocation instead of raw shell execution: |
| 61 | + |
| 62 | +```js |
| 63 | +const AGENT_CLI_MAP = { |
| 64 | + 'openclaw': { |
| 65 | + bin: 'openclaw', |
| 66 | + buildCmd: (message, context) => { |
| 67 | + const parts = [ |
| 68 | + 'openclaw', 'agent', |
| 69 | + '--session-id', 'textagent-openclaw', |
| 70 | + '--local', |
| 71 | + '--message', JSON.stringify(message), |
| 72 | + '--json', |
| 73 | + '--timeout', '300' |
| 74 | + ]; |
| 75 | + return parts.join(' '); |
| 76 | + } |
| 77 | + }, |
| 78 | + // openfang → daemon-based REST at 127.0.0.1:50051 |
| 79 | +}; |
| 80 | +``` |
| 81 | + |
| 82 | +### API Key Forwarding |
| 83 | + |
| 84 | +All major provider keys are auto-forwarded from the host environment into the Docker container so OpenClaw can reach any LLM backend: |
| 85 | + |
| 86 | +```js |
| 87 | +const FORWARDED_ENV_KEYS = [ |
| 88 | + 'OPENAI_API_KEY', |
| 89 | + 'ANTHROPIC_API_KEY', |
| 90 | + 'GOOGLE_API_KEY', |
| 91 | + 'GROQ_API_KEY', |
| 92 | + 'MISTRAL_API_KEY', |
| 93 | + 'TOGETHER_API_KEY', |
| 94 | + 'OPENROUTER_API_KEY', |
| 95 | + 'DEEPSEEK_API_KEY', |
| 96 | + 'XAI_API_KEY', |
| 97 | +]; |
| 98 | +``` |
| 99 | + |
| 100 | +### Structured Response Parsing |
| 101 | + |
| 102 | +OpenClaw returns JSON. The server extracts the human-readable reply intelligently: |
| 103 | + |
| 104 | +```js |
| 105 | +const replyText = |
| 106 | + agentResponse.choices?.[0]?.message?.content // OpenAI-compatible |
| 107 | + || agentResponse.payloads?.[0]?.text // OpenClaw payloads |
| 108 | + || agentResponse.reply |
| 109 | + || agentResponse.text |
| 110 | + || agentResponse.message |
| 111 | + || agentResponse.output |
| 112 | + || rawResult.stdout; // Fallback to raw |
| 113 | +``` |
| 114 | +
|
| 115 | +### Security Boundaries |
| 116 | +
|
| 117 | +Every OpenClaw execution runs **inside a Docker container**, not on the host: |
| 118 | +
|
| 119 | +- Dangerous commands blocked (`rm -rf /`, `mkfs`, `dd if=`, fork bombs) |
| 120 | +- Agent type sanitized (alphanumeric + hyphens only) |
| 121 | +- 360-second timeout per command |
| 122 | +- 64 KB output cap per stream |
| 123 | +- Containers auto-removed on idle or SIGTERM |
| 124 | +
|
| 125 | +--- |
| 126 | +
|
| 127 | +## Try It Now |
| 128 | +
|
| 129 | +1. Install [Docker Desktop](https://docs.docker.com/get-docker/) |
| 130 | +2. Clone the agent runner: |
| 131 | + ```bash |
| 132 | + git clone https://github.com/textagent/agent-runner.git |
| 133 | + cd agent-runner |
| 134 | + node server.js |
| 135 | + ``` |
| 136 | +3. Open [TextAgent](https://textagent.github.io), paste an Agent Flow block with `@agenttype: openclaw`, and click ▶ |
| 137 | +
|
| 138 | +--- |
| 139 | +
|
| 140 | +## Files Changed |
| 141 | +
|
| 142 | +| File | Change | |
| 143 | +|------|--------| |
| 144 | +| `agent-runner/agents/openclaw/Dockerfile` | Python 3.12 → Node.js 22 + `npm install -g openclaw@latest` | |
| 145 | +| `agent-runner/agents/openfang/Dockerfile` | Python 3.12 → Node.js 22 + `npm install -g openfang@latest` | |
| 146 | +| `agent-runner/agents/openclaw/requirements.txt` | Cleared (Node.js-based) | |
| 147 | +| `agent-runner/agents/openfang/requirements.txt` | Cleared (Node.js-based) | |
| 148 | +| `agent-runner/server.js` | `AGENT_CLI_MAP`, `FORWARDED_ENV_KEYS`, native CLI invocation, JSON response parsing, idle timer | |
| 149 | +| `agent-runner/scripts/setup.sh` | Removed git clone/pip; added API key guidance | |
0 commit comments