Aye Robot / Crusty — X automation (historical pause + unpause plan)¶
| Field | Value |
|---|---|
| Status | Aye Robot gate unlocked (2026-04-27): image + Telegram + brainstorm → pick → approve → xurl live post to X verified E2E. Steady-state transport: xurl + OpenClaw skills/xurl/SKILL.md. 2026-04-29: Model routing rollback on Crusty (grok-4-1-fast-reasoning primary; grok-4.20 orchestrator paused — token economics); daily Telegram job tweak for consistent images. Next concrete step: mentions listen path (scheduled xurl/API read → Telegram digest → optional Telegram-gated xurl reply) — canonical spec: projects/ayerobot-comic#next-concrete-step--mentions-listen-path. In parallel (~1 week): post path reliability. Routing history: projects/crusty (Model routing + Steady-state economics). Historical: 2026-04-18 pricing unblock. |
| Scope | Autonomous daily comic loop on dedicated Mac (Crusty): @ayerobotcomic |
| Co-priority with | projects/operator-agent — the two share Crusty's stack in non-conflicting ways (operator = ops skills, aye robot = post/listen skills). |
Canonical detail for why the full agent loop stopped short of unattended X posting via consumer web, and how it unblocked onto X API v2 + OpenClaw skills. Published comic workflow and agent stack overview: projects/ayerobot-comic, projects/crusty. Next concrete build after gate unlock — Next concrete step — mentions listen path on projects/ayerobot-comic. Cross-cutting debug patterns: recurring-issues (tool adapter, credential / key sources, session JSONL vs gateway logs).
2026-04-21: Unpause — E2E unblocked (Crusty host)¶
State (2026-04-21 history): Unblocked for image + bring-up X script. Steady state (2026-04-27): X posting is xurl + skills/xurl/SKILL.md (OAuth 2.0 PKCE, dev app) — not post_comic_test.py. Image generation works (workspace grok-imagine skill calling xAI grok-imagine-image). post_comic_test.py remains reference / archive (OAuth 1.0a from .env). Crusty runs the full pipeline (ideas → pick → Telegram gate → xurl post); see Status table and Still open above.
What we fixed (in order)¶
| # | Problem | Root cause | Fix |
|---|---|---|---|
| 1 | Config rejected by gateway | Invalid JSON (missing braces, wrong nesting) | Rewrote tail of ~/.openclaw/openclaw.json to valid JSON |
| 2 | Config rejected by schema | x_api is not a recognized top-level key in OpenClaw's schema |
Removed x_api from JSON; X credentials live only in ~/.openclaw/.env |
| 3 | Gateway reload failures | Stale grok-imagine-image entry under models.providers.xai.models with perImage / output keys the schema rejects |
Removed the image model entry — xAI image gen does not use the models path |
| 4 | image_generate tool failing |
imageGenerationModel.primary pointed at a non-existent xAI backend |
Removed imageGenerationModel entirely (OpenClaw only registers comfy / fal / google for that hook) |
| 5 | Skill looked “not working” when Crusty tried | Crusty used compound shell (cd X && python3 Y && ls Z); OpenClaw exec preflight rejects compound commands |
SKILL.md: absolute-path single-command example + explicit “no cd && chaining” rule |
| 6 | SKILL.md helper path wrong | Text pointed at ~/.openclaw/skills/ |
Actual install: ~/.openclaw/workspace/skills/ |
| 7 | Crusty truncating responses mid-output | xAI API key throttled at 60 TPM | Raised to 10M TPM / 1,800 RPM at console.x.ai |
| 8 | post_comic_test.py broken after removing x_api from JSON |
Old loader required a JSON block | .env fallback: reads the four X_* vars directly |
| 9 | comic.json / short-comic.json corrupted |
Bad patch: unknown command field, missing } |
Restored to valid {prompt, n} — prompt carriers, not flow definitions |
| 10 | projects.md one physical line with literal \n |
Earlier tool serialization bug | Expanded escape sequences to real newlines |
| 11 | Crusty reached for image_generate instead of grok-imagine for the daily comic |
No durable instruction in loaded context | Documented pipeline in workspace projects.md (Aye Robot), tool rule in TOOLS.md (Image Generation), breadcrumb in MEMORY.md |
Image generation — working pattern (Crusty)¶
- Location:
~/.openclaw/workspace/skills/grok-imagine/(workspace-scoped; appears inopenclaw skills list). - Invocation (Crusty — one direct command, no shell chaining):
python3 ~/.openclaw/workspace/skills/grok-imagine/generate_image.py "PROMPT" - Auth:
XAI_API_KEYin process environment, populated from~/.openclaw/.env. - Output:
.jpgunder~/.openclaw/media/outbound/with agrok_imagine_<timestamp>_1.jpgname; stdout shows✅ Saved:with the absolute path. - Mechanism:
POSThttps://api.x.ai/v1/images/generations, modelgrok-imagine-image, download URL to disk.
Rule: Use grok-imagine, not OpenClaw's image_generate tool, for this comic pipeline.
What lives where (Crusty host)¶
| Path | Role |
|---|---|
~/.openclaw/openclaw.json |
Clean JSON: no x_api, no imageGenerationModel; text models under xAI only |
~/.openclaw/.env |
Secrets: XAI_API_KEY, X_CONSUMER_KEY, X_CONSUMER_KEY_SECRET, X_ACCESS_TOKEN, X_ACCESS_TOKEN_SECRET |
~/.openclaw/workspace/skills/grok-imagine/ |
Image-gen skill + fixed SKILL.md |
~/.openclaw/workspace/projects.md |
Full Aye Robot pipeline (ideas → pick → prompt → grok-imagine → reply; no auto-post) |
~/.openclaw/workspace/TOOLS.md |
Rule: grok-imagine, never image_generate, single command only |
~/.openclaw/workspace/MEMORY.md |
Breadcrumb to projects.md + TOOLS.md |
~/.crusty/post_comic_test.py |
Standalone X poster; reads creds from .env; supports --dry-run |
Still open (separate from core unpause)¶
- Crusty model routing — two-tier live; Phases 3–4 complete (2026-04-27). projects/crusty Model routing. Optional Phase 5 sub-tier (non-reasoning for digests) still deferred.
- Posting transport:
xurl+skills/xurl/SKILL.md— live (first E2E post 2026-04-27).post_comic_test.py= bring-up / reference. - Image scheduling: LIVE 2026-04-27 — morning cron → Telegram with a fresh grok-imagine panel.
- X-post + gate: Live — caption + image (or equivalent package) to Telegram → manual approval →
xurl; proven same day as gate unlock. - Live X post: Shipped on the
xurlpath (2026-04-27). Next: mentions listen path (see projects/ayerobot-comic#next-concrete-step--mentions-listen-path); post-path reliability in parallel (~1 week). - Wiki / handoff: This projects-wiki repo is now aligned with the above; any other copy of the old model (e.g. stale notes with
x_apiin JSON orimage_generatefor images) should be updated before handoff.
2026-04-21: Next steps — switch transport to xurl (X's official CLI)¶
Why xurl over post_comic_test.py: the Python script was a bring-up tool that proved credentials + policy + pricing shape in dry-run. The steady-state transport should be the CLI X itself ships — no homemade OAuth plumbing to babysit, native media upload, natural-language surface through OpenClaw's already-merged skills/xurl/SKILL.md (Crusty auto-recognizes it). No Playwright, no custom script maintenance, no third-party bridges.
Confirmed prerequisites (as of 2026-04-21):
- Dev app exists on the band X account. Client ID + Client Secret issued, package set to Pay-per-use, environment set to Production — both of these are required or xurl calls will 401 with
client-forbidden. (reference tweet) - Target post account: @ayerobotcomic (the handle the comics actually publish from).
- Crusty isolation preserved: no personal creds, no this-repo access, xAI/Grok-only model stack, Telegram approval gate carries over.
- Comic format unchanged: single-panel sci-fi humor image (grok-imagine skill) + caption; image leg on a morning schedule to Telegram (2026-04-27); post leg via
xurlafter Telegram approval live (2026-04-27).
Handoff steps (run the auth steps manually on Crusty — do not let the agent handle secrets):
- ~~Prerequisite — Crusty model routing Phases 3–4.~~ Complete 2026-04-27 per projects/crusty Model routing — two-tier live; Aye Robot gate unlocked (E2E Telegram →
xurl). Treat this step as historical for new installs; do not re-sequence a live post before routing on a fresh machine. - ~~Install
xurlon Crusty (one-time, terminal) — done 2026-04-27.~~ Original steps kept for new-machine / disaster recovery: - Preferred on the dedicated macOS laptop:
brew install --cask xdevplatform/tap/xurl - Cross-platform alternative:
npm install -g @xdevplatform/xurl - One-liner fallback:
curl -fsSL https://x.dev/xurl/install | bash - ~~Authenticate (OAuth 2.0 PKCE) — done 2026-04-27.~~ Original flow for rebuilds:
- Register the app:
xurl auth apps add ayerobot-app --client-id <CLIENT_ID> --client-secret <CLIENT_SECRET> - Start OAuth 2.0 flow (opens a browser):
xurl auth oauth2 - Verify:
xurl auth status - Optional convenience:
xurl auth default ayerobot-app - ~~Smoke-test in terminal first — done 2026-04-27.~~ For verification after reinstall:
xurl whoami→ should return @ayerobotcomic.xurl timeline -n 3→ confirms read path.xurl post "Test from Crusty xurl — ignore this"→ first live tweet; verify it actually appears on the profile.- ~~Restart OpenClaw gateway / agent~~ (done 2026-04-27 when
xurlpath went live) — on rebuild: so it picks up the localxurlbinary and the mergedskills/xurl/SKILL.md. - ~~Update the daily Aye Robot prompt~~ (done 2026-04-27) — use xurl end-to-end (natural language; the skill handles the subcommands):
- Generate today's panel with grok-imagine (single-panel sci-fi sarcasm, newspaper-cartoon style); save as
~/.openclaw/media/outbound/aye-robot-YYYY-MM-DD.jpg. - Draft caption.
- Send image + caption to Telegram for human approval.
- On approval, post via xurl — e.g.
xurl post "[full caption] #AyeRobotComic" --media ~/.openclaw/media/outbound/aye-robot-YYYY-MM-DD.jpg(checkskills/xurl/SKILL.mdfor the exact media flag — the skill abstracts media upload). - Capture the returned post URL / ID; log success (and optionally
xurl read <post-id>or axurl timeline -n 1to verify). - Next concrete step (2026-04-27) — Wire the mentions listen path: scheduled read (
xurl/GET /2/users/{id}/mentions/xurl searchas appropriate) → Telegram digest to Darcy → optional draft reply →xurl replyonly after the same Telegram human-gate as the comic post. Canonical numbered spec: projects/ayerobot-comic#next-concrete-step--mentions-listen-path. (The X-post + grok-imagine + approval post path is live; image morning cron is live — see Status above.)
What this retires:
~/.crusty/post_comic_test.py— demoted to bring-up / archive reference (first livexurlpost shipped 2026-04-27). Credentials it reads (X_CONSUMER_KEY/X_CONSUMER_KEY_SECRET/X_ACCESS_TOKEN/X_ACCESS_TOKEN_SECRETin~/.openclaw/.env) can stay in place — they're independent of xurl's OAuth 2.0 token store — but they're not the steady-state posting path. Don't build new skills on top of them.- The old "write our own media-upload wrapper" branch of the plan — xurl handles v2 media upload natively; v2 media-upload pricing is still a standing open question (below), but the mechanism no longer needs custom code.
Why this is cleaner than the prior path:
- Official, supported, local:
xurlis X's own CLI; no third-party bridge, no scraping, no browser. - OpenClaw already recognizes it:
skills/xurl/SKILL.mdis merged upstream, so Crusty gets a natural-language surface (xurl post,xurl reply,xurl search,xurl timeline) without us writing a skill. - Pay-per-use pricing unchanged: ~$0.015 / text post, ~$0.001 / owned read, ~$1.20/mo at current cadence.
- Policy posture unchanged: still API v2, still inside X's automation "Do" examples (image-only, image-only lead post, human-gated replies).
Goal¶
Autonomous daily comic loop on a dedicated Mac (Crusty): generate image (xAI) → Telegram approval → post to X (@ayerobotcomic) → monitor replies. Stack is OpenClaw (agent / gateway), xAI-only models per project constraints.
What is verified and working¶
- OpenClaw workspace and tooling on the host: agent workspace and skills area healthy; image / memory / media directories in place. 2026-04-21: Workspace grok-imagine skill is the supported image path for the comic (not OpenClaw's built-in
image_generate). Paths on the Crusty machine: see What lives where above. - xAI API: Authentication and calls validated (direct
/v1/models, assistant turns). Key-sourcing pattern (actual, confirmed 2026-04-20): xAI and X secrets live in Crusty's~/.openclaw/.env; OpenClaw JSON stays schema-clean (no top-levelx_api). Config may reference vars via${env:VAR}where applicable — not duplicated into shell profile files (.zshrc/.bash_profile). → recurring-issues (key / env sprawl — aspirational-vs-actual resolution). - Shell / exec tool: Confirmed real subprocess execution via the agent's session-log audit trail — look for exec-tool entries with exit code and duration. Do not rely on the gateway log for shell proof; the session log is the audit trail. Exec constraint: OpenClaw rejects compound shell commands — skills and docs must use one absolute-path command (no
cd &&chains). → recurring-issues (gateway log ≠ ground truth). - Image generation (comic): grok-imagine skill →
POSTxAI Images API (grok-imagine-image), files land under~/.openclaw/media/outbound/. Do not route this throughmodels.providers.xai.modelsorimageGenerationModel— those paths do not apply to xAI image gen on this stack. - X API posting (steady state): X's official
xurlCLI + OpenClaw's mergedskills/xurl/SKILL.md— OAuth 2.0 PKCE with the dev app; install + auth + first live post complete 2026-04-27 — see Next steps — switch transport to xurl. Bring-up script (historical):~/.crusty/post_comic_test.py— OAuth 1.0a,X_*from.env; was dry-run + bring-up only. - Telegram: Bot/channel wired through OpenClaw config; generate → Telegram → approve →
xurlpost path live (2026-04-27). Next build = mentions listen path (see Still open / Status). - Local automation sandbox: Separate local sandbox directory (Python venv, browser profile, logs, skills), Playwright + Chromium installed in venv — for non-X recon only; X transport is API-only.
- Playwright smoke: Can launch the browser with persistent user-data dir and open pages; not used for @ayerobotcomic posting (policy + design).
Where it stalled (not reliable for autonomy yet)¶
Posting to X via browser automation (Playwright + Brave + consumer x.com UI) is not a stable foundation for a fully autonomous agent today — and as of the 2026-04-20 re-read of X's automation rules it is also explicitly prohibited:
- Policy (hard stop): X's automation rules state "Don't use non-API-based automation like scripting the X website", and explicitly flag that doing so can result in permanent account suspension. This closes the browser-automation path as a design option, not just as an engineering one. @ayerobotcomic is a dedicated account with real follower count; a ban has no upside.
- Engineering (why it was fragile anyway): X treats automated browsers harshly (login flows resetting, anti-bot behavior); "log in manually with plain Brave using the same profile" + "reuse cookies in Playwright" did not converge to a repeatable, unattended logged-in state; the "controlled by automated test software" surface is detectable and the mitigations are a moving target.
So: infrastructure for image + exec + Telegram is in good shape; unattended X posting through the web app is the weak link, not OpenClaw itself — and per X policy it can't be the transport regardless of how stable we made it.
Design decisions recorded¶
- A local sandbox holds venv, browser profile, and future posting scripts; the agent-visible workspace holds OpenClaw-tracked skills. Kept deliberately separate.
- JSON receipts on stdout, human trace on stderr for skills — for orchestration and postmortems.
- Diagnostic habit: UI weirdness or dropped tool calls → check the gateway error log and auth before blaming the model.
If you resume later (high level)¶
- X posting transport = X API only. Browser automation is policy-prohibited, not merely discouraged (see X automation rules). The only other permitted channels are manual human post or a different platform. Do not re-open the Playwright + consumer-web path.
- Keep the agent's session-log audit trail as ground truth for whether tools actually ran.
2026-04-18: Unpause signal — X API pricing change¶
What changed (announced 2026-04-17, effective 2026-04-20):
- No subscription gate. X API is now pay-per-use, credit-based, no Basic/Pro tier required — see X API pricing. Auto-recharge + spending limits available in the Developer Console.
- Owned reads (own posts, mentions, followers, lists metadata, etc.): $0.001/request (1,000 for $1). Deduplicated within 24-hour UTC window.
- Text post via
POST /2/tweets: $0.015 (up from $0.01). - Post containing a URL: $0.20 per post (13x text). Summoned replies exempt at $0.01.
- Removed from self-serve tier entirely:
POST /2/users/{id}/following,POST /2/users/{id}/likes, quote-posts viaquote_tweet_id. - xAI credit rebate: 10–20% of X API spend back as xAI credits if you link teams (Crusty already runs xAI-only, so this is pure upside).
Why this matters for this project: the specific blocker — "unattended X posting through the web app is the weak link" — goes away when transport moves to the API. Transport was the fragility; nothing else in the stack was broken.
Unblock path (Crusty → X API, no browser):
- Replace the browser-automation posting skill with an OpenClaw skill calling X API v2 (
POST /2/tweets). Keep the Telegram approval gate unchanged — the gate is the human-in-the-loop safety net, not the transport. - Auth model = OAuth 1.0a user-context (four keys), not Bearer Token.
POST /2/tweetsis a user-context endpoint — app-only Bearer tokens can't call it (Bearer only works on read-mostly endpoints that support app-only auth). For a single-handle daily posting loop, use the four OAuth 1.0a keys from the developer app's user-context credentials: API Key, API Key Secret, Access Token, Access Token Secret. OAuth 2.0 Authorization Code + PKCE is the alternative but adds a refresh-token dance that isn't worth it for a single-owner handle. Storage: all four go into Crusty's.env(same file the xAI key already lives in — see note above); the OpenClaw config references them via${env:VAR}expansion. Reference implementation for this handoff:post_comic_test.pyuses OAuth 1.0a user-context with env-sourced secrets. → recurring-issues (key / env sprawl, aspirational-vs-actual resolution). - Image-attached posts via v2 media upload. Use
POST /2/media/upload(v2) — v1.1/media/uploadstill responds but the docs index now lists v1.1 media as legacy, so all new work should target v2. For anything that needs chunked / resumable upload, v2 exposes explicit routes:POST /2/media/upload/initialize→POST /2/media/upload/:id/append→POST /2/media/upload/:id/finalize. Reference the returnedmedia_idfrom the post body when callingPOST /2/tweets. Verify v2 media pricing before committing — the 2026-04-17 pay-per-use announcement coveredPOST /2/tweetsbut did not explicitly quote v2 media-upload pricing. - Mentions polling via
GET /2/users/{id}/mentionson an hourly cron is cheap (~$0.72/mo at 1/hr). Wire into Telegram for reply drafting. Optionally batchGET /2/tweetswithtweet.fields=public_metricson recent @ayerobotcomic ids a few times per day for an engagement rollup (same owned-read pricing) — projects/ayerobot-comic#post-engagement-metrics-poll. - Leave the local sandbox (Playwright + browser + venv) installed but idle for non-X recon only. Do not revive the X browser-profile path — X's automation rules treat "scripting the X website" as a permanent-suspension offense.
Rough monthly cost at current cadence (1 comic/day + hourly mentions poll + optional post-metrics poll):
| Line | Volume | Cost |
|---|---|---|
| Comic posts (image-only, no URL) | 30 | $0.45 |
| Mentions poll, hourly | 720 | $0.72 |
| Post metrics poll (e.g. 3/day, batched ids) | ~90 | $0.09 |
| Own-timeline spot checks | ~30 | $0.03 |
| Subtotal | ~$1.29/mo | |
| xAI rebate at $0 spend tier | 0% | $0 |
If comic posts link to anywhere (archive URL, band site, etc.), each such post costs $0.20 instead of $0.015 — that's $6/mo extra at daily cadence for the URL alone. Design implication: image-only primary post; put any link in a summoned reply ($0.01) or in the bio.
What the pricing change does NOT fix:
- Growth patterns that relied on auto-like / auto-follow / quote-post are dead on self-serve. Growth strategy must shift to original-content-attracts-mentions + manual-gated replies. Reply-to-mentions is allowed at $0.01.
- Content-policy risk unchanged. X can still suspend the account if posts look spammy; API access doesn't buy leniency. Keep Telegram approval gate in place — and per X automation rules, "account holders are ultimately responsible for automated activity on their accounts," which means the gate is now the policy-aligned design, not just a defensive one.
- API terms/pricing can change again. Elon's history suggests the pricing now is not the pricing forever. Keep the posting skill abstracted enough to swap transports (to another platform entirely — not back to browser automation, which is policy-prohibited regardless of future API price hikes).
Open questions to resolve before full “daily unattended” operation:
- [ ] v2 media upload pricing — is
POST /2/media/upload(and the chunkedinitialize/append/finalizeroutes) in the owned-reads $0.001 bucket, separate, or bundled with the post? Check the rate card in Developer Console. Mechanism is now handled byxurlregardless; this is pure cost-model hygiene.
Closed (2026-04-21):
- ~~Image generation upstream of posting~~ — Resolved: workspace grok-imagine skill + valid OpenClaw JSON/schema (see fix table above). ~~Scheduling +
xurllive post~~ — Resolved 2026-04-27 (morning cron + E2Exurlafter approval); not image capability. - ~~Dev-app provisioning~~ — Resolved: dev app already exists on the band X account with Client ID + Secret, Pay-per-use package, Production environment. (Pay-per-use + Production are both required; without them xurl errors with
client-forbidden.) → See Next steps — xurl.
Closed (2026-04-20, by re-reading X automation rules):
- ~~Is 1 image/day close enough to "normal human account behavior" that suspension risk is low?~~ — Yes. X's own rules list "Automatically broadcast helpful information in posts" as an allowed use case, alongside auto-replies to engaged users and DM auto-responders. A single image-only daily post + human-gated mentions reply is squarely inside the named "Do" examples, not gray-zone.
Decision rule (historical): the pricing + API path cleared the old Paused state. 2026-04-21: treat the project as Active on the stack (image + post script); finish scheduling, live smoke-test post, and any Telegram approval productization as separate checklist items.
Policy posture (2026-04-20, X automation rules)¶
Re-reading X's automation policy simplifies the project: the current design is explicitly inside the "Do" list and the tempting fallback is explicitly in the "Don't" list.
| X rule | Applies here as |
|---|---|
| Do: "Automatically broadcast helpful information in posts" | Daily one-panel comic via X API v2 — named allowed use case. |
| Do: "Build solutions that automatically respond to users in Direct Messages" + "Run creative campaigns with auto-replies to engaged users" | Mentions-polling + Telegram-gated reply workflow — allowed, no separate approval needed from X. |
| Don't: "Use non-API-based automation like scripting the X website" — can result in permanent account suspension | Browser automation (Playwright / Brave consumer UI) is permanently off the table for @ayerobotcomic, not just paused. Combined with the 2026-04-17 pay-per-use pricing, API v2 is the only transport that is both economic and compliant. |
| Don't: spam / unsolicited messages | 1 image/day, no cold DMs, no auto-follow, no auto-like, no quote-post farming. (Three of those four are also removed from self-serve API as of 2026-04-17, so this is belt-and-suspenders.) |
| "Account holders are ultimately responsible for automated activity on their accounts." | Telegram approval gate is now policy-aligned, not just defensive design. Keeps Darcy in the loop for any state-changing action. |
| Restricted: off-X matching (linking X usernames to external identifiers requires explicit opt-in) | Not in scope today. Guardrail if @ayerobotcomic ever builds analytics that join replies to external IDs. |
| Restricted: redistribution — use Post IDs, DM IDs, User IDs, not full content | Guardrail for any future archive/mirror of comic replies. |
Net effect on the unpause plan: one design option killed (browser automation — hard no, permanent), one open question closed (cadence is clearly compliant), the Telegram gate gets a stronger "why," and the rest of the 2026-04-18 plan (port to X API v2, reuse Telegram gate, hourly mentions poll, optional batched post-metrics reads) is unchanged and explicitly endorsed by policy.
Note on community¶
There is no requirement that “many OpenClaw users” ship X posting in autonomous loops. Browser-driving a consumer social network from an agent is inherently brittle; pausing to reconsider is reasonable and does not imply OpenClaw is unsuitable — only that this integration needs a different contract (API, human gate, or another channel).
Related¶
- projects/ayerobot-comic — public channel + current human-in-the-loop workflow.
- projects/crusty — instance doc, historical handoff, easiest-path strategy.
- recurring-issues — tool-adapter class failure, key / env sprawl, session-log vs gateway-log audit trail.
- projects/openclaw-autonomy-org — umbrella context.