OpenHands + Fable 5: Autonomous Issue to Pull Request
Hand Fable 5 a GitHub issue and let OpenHands plan, edit, run tests, and open a PR in a Docker sandbox.
Run this workflow
CI-verified, 4/4 fixtures passing.
Build this with your agent
One copy-paste hands Claude Code, Codex, or Cursor the full recipe, steps included, nothing to fetch.
Intended Use
Watching an agent run autonomously: OpenHands works in a Docker sandbox with shell, editor, and browser, turning an issue into a PR. CI verifies the deterministic spine: the settings config parses, llm.model equals anthropic/claude-fable-5, and the runtime and agent keys are present and well-typed. No key. The agent reading the issue and writing the fix is the fenced model step.
Not for
- Giving an autonomous agent --always-approve on a real repo; keep confirmation mode on for anything that pushes
- Setups without a working Docker socket (the default runtime)
- Expecting CI to verify the PR; that is the fenced model step
The Stack
Tested Against
openhands@1.8.xclaude-fable-5Side effects & data flow
- Network
- none, local only
- Writes
- ./settings.json, ./checkopenhands.mjs
- Credentials
- none required
Prerequisites
- Docker (default runtime)
- uv (uv tool install openhands --python 3.12)
- An Anthropic API key for anthropic/claude-fable-5
Steps
- 1
Install OpenHands and set Fable as the model
uv tool install openhands --python 3.12, then openhands -t 'Reproduce and fix the bug in issue #142, add a regression test, open a PR'. Set the model on first run or in settings: the [llm] block is model = anthropic/claude-fable-5, api_key = <your key>.
- 2
What CI checks: the settings parse and name Fable
CI confirms the settings config parses, llm.model equals anthropic/claude-fable-5, and the runtime and agent keys are present and well-typed. Deterministic, no key. The autonomous run is fenced.
cat > settings.json <<'EOF' { "llm": { "model": "anthropic/claude-fable-5", "api_key": "<your-anthropic-key>" }, "runtime": "docker", "agent": "CodeActAgent" } EOF cat > checkopenhands.mjs <<'EOF' import { readFileSync } from 'node:fs'; const cfg = JSON.parse(readFileSync('settings.json', 'utf8')); let ok = true; function check(label, cond){ console.log(label + ': ' + (cond ? 'yes' : 'NO')); if(!cond) ok=false; } check('settings parse', true); check('llm.model is anthropic/claude-fable-5', !!cfg.llm && cfg.llm.model === 'anthropic/claude-fable-5'); check('runtime key present and typed', typeof cfg.runtime === 'string' && cfg.runtime.length > 0); check('agent key present and typed', typeof cfg.agent === 'string' && cfg.agent.length > 0); if(!ok){ console.log('openhands config check FAILED'); process.exit(1); } console.log('openhands config check OK: llm.model anthropic/claude-fable-5'); EOF node checkopenhands.mjs - 3
Let it open the PR (the model step, not checked by CI)
OpenHands runs Fable in the sandbox to fix the issue and open a PR. That is non-deterministic and is fenced. Keep confirmation mode on for anything that pushes.
Eval, 4 fixtures
Last passed: verified todayllm-modelcontainstimeout 30s · max $0Expected:
llm.model is anthropic/claude-fable-5: yesruntime-keycontainstimeout 30s · max $0Expected:
runtime key present and typed: yescheck-okcontainstimeout 30s · max $0Expected:
openhands config check OK: llm.model anthropic/claude-fable-5clean-exitexit_codetimeout 30s · max $0Expected:
0
Results
~76.4k stars; where Fable's token efficiency compounds hard, an agent that loops for hundreds of steps.
Did this work for you?
Our CI checks the setup runs. You tell us if the whole thing worked. Tell us straight.
Liked this workflow?
Get new verified workflows in WebAfterAI, three issues a week (Tue, Thu, Sat).