Install
openclaw skills install overnight-factorySet up an AI agent as an Overnight Software Factory operator. Use when configuring an OpenClaw agent to autonomously handle support tickets end-to-end: receive ticket assignments via email or GitHub, analyze issues, spawn Claude Code to implement fixes, open PRs, and notify a human for review. Triggers on phrases like "set up overnight factory", "configure ticket pipeline", "automate support tickets", "set up AI coding agent for tickets", or "overnight software factory".
openclaw skills install overnight-factoryConfigure this agent as an autonomous ticket-to-PR operator. Human reviews PRs; agent handles everything else.
TinyDesk/support system
→ GitHub issue (assigned to bot account)
→ Email notification to agent inbox
↓
Cron job (every 15min, isolated session)
├─ Email check: detect assignment emails
├─ GitHub poll: catch missed emails (safety net)
└─ Dispatch: spawn subagent per ticket
↓
Subagent (Claude Code)
├─ Analyze issue + screenshots
├─ Explore codebase
├─ Post analysis comment on issue
├─ Implement fix (branch → commit → push)
└─ Open PR → notify human
Create workspace files: IDENTITY.md, USER.md (who you're helping), SOUL.md.
Add .env to workspace:
GITHUB_TOKEN=ghp_...
EMAIL_USER=support@yourdomain.com
EMAIL_PASSWORD=...
Configure git:
git config --global user.name "Your Bot Name"
git config --global user.email "bot@yourdomain.com"
echo "https://bot-username:${GITHUB_TOKEN}@github.com" > ~/.git-credentials
git config --global credential.helper store
/path/to/claude --version
/path/to/claude -p --dangerously-skip-permissions --output-format text "echo hello"
Note the exact path — you'll need it.
openclaw cron add \
--name "email-check" \
--every 15m \
--session isolated \
--announce \
--to <YOUR-TELEGRAM-CHAT-ID> \ # explicit ID, NOT --channel last
--timeout-seconds 120 \
--description "Check email + GitHub for ticket assignments" \
--message "$(cat /path/to/cron-prompt.txt)"
See references/cron-prompt.md for the full prompt template.
The cron handles email. Heartbeat should only contain tasks that need main-session context (e.g., PR monitoring).
Cron delivery: Always use --to <explicit-chat-id>. Never --channel last — it doesn't resolve in isolated sessions.
Cron timeout: Keep the prompt fast. Check email → spawn subagents → log → exit. Never wait for subagents inline. 120s is enough.
Error backoff: After 5+ consecutive errors the cron backs off exponentially. Delete and recreate to reset: openclaw cron delete <id> && openclaw cron add ...
Fire-and-forget: Subagents don't reliably call back to Telegram. Have the cron itself announce dispatches in its own reply (the cron reply is what gets delivered).
Before going live:
lastDelivered: false on empty runs is expected (HEARTBEAT_OK is silent by design)# Check cron status
openclaw cron list --json | jq '.jobs[0].state'
# Key fields to check:
# lastRunStatus: "ok" or "error"
# consecutiveErrors: should be 0
# lastDelivered: false on empty runs is normal; false on ticket-dispatch runs is a bug
# lastDeliveryStatus: "not-delivered" = delivery config wrong
# Check recent logs
tail -20 memory/heartbeat-log.jsonl
# Check inbox directly
python3 -c "
import imaplib, ssl
ctx = ssl.create_default_context()
M = imaplib.IMAP4_SSL('imap.ionos.com', 993, ssl_context=ctx)
M.login('user@domain.com', 'password')
M.select('INBOX')
print('Unread:', len(M.search(None, 'UNSEEN')[1][0].split()))
M.logout()
"
references/cron-prompt.md — full cron job prompt template with email check + GitHub pollreferences/ticket-pipeline.md — how to instruct subagents to handle tickets end-to-endreferences/lessons-learned.md — real failure modes and fixes from production use