Install
openclaw skills install @workingdevshero/automate-itCreate content tasks and automations in Automate It, do the content work yourself or leave it to the built-in worker, poll task status through the human review gate, and fetch links to published posts. Use when asked to draft, schedule, or publish social content via Automate It, or to check the status or published results of a submitted task.
openclaw skills install @workingdevshero/automate-itAutomate It is a content platform with a human review gate: tasks describe content to create, a worker generates the content, a human reviews and approves it, and it publishes to the connected platforms (X, LinkedIn, Instagram, Threads, Facebook, Discord, Bluesky, articles, and more).
You can participate two ways:
--claim, attach your content, complete it into the human review queue. Automate It provides the review checkpoint and the credentialed publishing; you provide the brains.All commands use the bundled CLI: ./ait.mjs (Node 18+ or Bun; also runs as node ait.mjs …). It speaks the same MCP server that human-driven clients (Claude Code, etc.) use, so anything the platform exposes as a tool is available — ./ait.mjs tools lists everything, and ./ait.mjs call <tool> --args '<json>' calls any tool the named commands don't wrap. Errors print {"error": "..."} to stderr and exit 1.
Required environment:
AUTOMATE_IT_API_KEY — an Automate It API key (starts with ak_). The human operator creates this in Automate It under Profile → API keys.AUTOMATE_IT_WORKSPACE (optional) — default workspace id. If unset and the key has exactly one workspace, it is auto-resolved. Every command also accepts --workspace <id>.AUTOMATE_IT_API_URL (optional) — defaults to https://api.automate.it.com.Verify access before doing real work:
./ait.mjs workspaces # workspaces the key can reach
./ait.mjs whoami # the user you act as
If a command fails with MCP HTTP 401, the key is missing, mistyped, or revoked — stop and tell the operator. If it fails with missing required scope, the key lacks a scope (see Permissions) — report which one is missing rather than retrying.
Use this when you (or your runtime) already produce the content and Automate It's job is human approval + publishing.
Create the task already claimed. --claim creates it in working status, so the built-in worker never touches it — there is no race to lose.
./ait.mjs task create --claim \
--title "Post about the v2.0 launch" \
--instructions "Context for reviewers: announcing Acme v2.0" \
--output-types x
The response includes the task JSON — save the id.
Claiming assigns the task to you: the built-in worker never touches it, the platform's dead-task recovery leaves it alone (that sweep is for the built-in worker's own crashed runs), and a later rejection routes back to you. Take as long as the content needs — but don't abandon a claimed task: nothing times it out, so it sits in working until you complete it or a human deletes it.
Attach your content. One call per content item; use sortOrder for threads (0 = first post).
./ait.mjs task add-content <taskId> --type x \
--body "Acme v2.0 is live — new API, faster everything. https://acme.dev/blog/v2"
For images/video: get a presigned URL, PUT the file, then reference it:
./ait.mjs upload-url --filename hero.png --mime-type image/png
# PUT your file to the returned uploadUrl, then:
./ait.mjs task add-content <taskId> --type x --body "..." \
--media '[{"type":"image","url":"<permanentUrl>"}]'
Complete it into review.
./ait.mjs task complete <taskId>
The task lands in the human review queue (review status). From here it's the same as delegate mode: poll, and fetch links after publish.
If your content is already finished, skip the three-step loop entirely with the one-shot submit — it creates the task with the content attached and lands it directly in the review queue:
./ait.mjs task submit --title "Post about the v2.0 launch" --type x \
--body "Acme v2.0 is live — new API, faster everything. https://acme.dev/blog/v2"
If a human rejects your content, the task drops back to todo and revisionCount goes up. It is still assigned to you (claiming assigned it), so the built-in worker can't touch it. Reclaim it — task complete only accepts a task in working — then revise.
Revise in place. task add-content appends another post — use it again and the task carries both the rejected draft and the fix.
./ait.mjs task claim <taskId> # back to "working", yours again
./ait.mjs task get <taskId> # newest `comments` entry says why it was rejected
# each contentItems[] entry has the id you need
./ait.mjs task update-content <taskId> <contentItemId> --body "<revised copy>"
./ait.mjs task complete <taskId>
To rewrite a multi-post thread from scratch, ./ait.mjs task clear-content <taskId> first, then add each post again. task delete-content <taskId> <contentItemId> drops a single one.
Explain yourself if the reviewer's note was ambiguous, or if you deliberately didn't follow it:
./ait.mjs task comment <taskId> --comment "Kept the link — removing it drops the CTA."
Create the task without --claim. Describe the content in --instructions the way you would brief a copywriter: topic, angle, tone, audience, links to include.
./ait.mjs task create \
--title "Post about the v2.0 launch" \
--instructions "Write an upbeat announcement of Acme v2.0 for developers. Mention the new API and link to https://acme.dev/blog/v2." \
--output-types x,linkedin
Poll until it resolves. Poll every 60 seconds or so while generating; once it reaches review, a few checks an hour is plenty — humans are slow.
./ait.mjs task get <taskId>
| status | meaning | what you do |
|---|---|---|
todo | queued, not started | wait |
working | content is being generated | wait (in worker mode this means you owe content) |
review | waiting on a human reviewer | wait (slow — human in the loop) |
approved | human approved, not yet published | wait (or report approval) |
published | live on the destination platforms | fetch links, report success |
failed | generation or publish failed | report failure to the operator |
deleted | task was deleted by a human | stop tracking it, report |
Fetch the published links once status is published:
./ait.mjs task links <taskId>
Returns {"taskId": "…", "status": "published", "links": [{"platform": "x", "postUrl": "https://…", "postId": "…"}]} — report the postUrl values back to whoever asked.
--publish-mode manual): after approval, a human also clicks publish. Safest; use unless told otherwise.--publish-mode immediate: publishes automatically the moment a reviewer approves.--publish-mode scheduled --publish-at 2026-07-10T15:00:00Z: publishes at the given time after approval.--no-review skips the human review gate entirely (auto-publish on completion). Never use this unless the operator has explicitly told you to.Valid --output-types / --type values: x, linkedin, instagram, facebook, threads, discord, bluesky, article, email, carousel, podcast, rss, spreadsheet, document.
Only platforms the workspace has actually connected will publish. Don't guess and don't ask — check:
./ait.mjs call list_integrations # which platforms are connected
./ait.mjs call get_x_character_limit # 280 or 25000, depending on the plan
When a task publishes to rss and to social platforms, put the token {articleUrl} in the social post body. At publish time it's replaced with the article's real URL — which doesn't exist until the feed item is created, so you can't write it yourself.
./ait.mjs task add-content <taskId> --type article --title "Acme v2.0" --body "<the article>"
./ait.mjs task add-content <taskId> --type x --body "Acme v2.0 is live. Read more: {articleUrl}"
If the task has no rss output (or the feed publish fails), the token and the space before it are stripped, so the post still reads correctly. The token only resolves for rss — a podcast output does not populate it.
A skill is reusable instruction — brand voice, formatting rules, house style — plus any reference files bundled with it. Check for skills before you write anything.
./ait.mjs skills list # id, name, description
./ait.mjs skills get <skillId> # full instructions + bundled file ids
Attach them by name (or id) when creating a task:
./ait.mjs task create --title "Launch post" --skills "brand voice,changelog style" --claim
This is the part agents get wrong. Attaching a skill only does something when the built-in worker runs the task — it injects the instructions and files for you. In worker mode (--claim) the worker never runs, so nothing is injected. Read the instructions yourself with skills get and apply them. Attaching is still worth doing: it records which skills the content was written against.
Bundled files are workspace files. Fetch one by getting a URL and downloading it yourself:
./ait.mjs files download-url <fileId> # returns a time-limited downloadUrl
curl -o brand.pdf "<downloadUrl>"
./ait.mjs task list --status review # everything waiting on a human
./ait.mjs task list --limit 10 # recent tasks
./ait.mjs task get <taskId> # full detail for one task
./ait.mjs files list --search brand # workspace file browser
If tasks arrive from automations or teammates and you're the worker, take them one at a time:
./ait.mjs task claim-next # atomically claims the oldest todo task
Use this rather than task list --status todo followed by task claim <id>: those are two calls, and another worker can take the task in between. claim-next returns nothing when the queue is empty. It never hands you a task assigned to someone else.
Humans (or other agents) can assign tasks to your user instead of the built-in worker. Assigned tasks are invisible to the built-in worker — they wait for you. Check for them periodically, then run the normal work loop:
./ait.mjs task list --mine --status todo # work waiting on you
./ait.mjs task claim <taskId> # only the assignee can claim an assigned task
# … generate content …
./ait.mjs task add-content <taskId> --type x --body "..."
./ait.mjs task complete <taskId>
If a task you worked comes back with a higher revisionCount (a reviewer rejected it), you'll find it in task list --mine --status todo again — read the rejection comment via task get, revise in place with task update-content, and task complete again. Because it stays assigned to you, the built-in worker can't claim it out from under you while you revise.
You can also assign at creation: task create --assign <userId|me>, or task submit --assign me.
If your key belongs to a reviewer/admin and the operator has asked you to help triage, these exist: task next-review, task approve <id>, task reject <id> --comment "...", task publish <id>. Do not approve or publish content you produced yourself — the whole point of the review gate is that a different human (or their delegate) signs off.
A task is one-off; an automation is a standing brief that spawns tasks on a schedule. Use automations only when asked for recurring content.
./ait.mjs automation create --name "Weekly changelog roundup" \
--instructions "Summarize this week's merged changes as a friendly post." \
--output-types x --schedule '{"type":"cron","value":"0 9 * * 1"}'
./ait.mjs automation list
./ait.mjs automation get <automationId>
./ait.mjs automation update <automationId> --name "Renamed"
./ait.mjs automation run <automationId> # trigger now; returns the spawned task to poll
automation run returns a task — poll it with task get. If the response includes "alreadyRunning": true, an earlier run is still in flight; poll that task instead of triggering again.
./ait.mjs tools lists every tool the platform exposes (files, folders, integrations, URL shortening, …); call any of them with ./ait.mjs call <tool> --args '<json>'. workspaceId is injected automatically when omitted.
The API key's scopes bound what you can do (enforced server-side):
tasks:read — task list / get / links / next-reviewtasks:write — task create / claim / claim-next / complete / comment / approve / reject / publish / deletecontent:write — task add-content / update-content / delete-content / clear-content, and task submit (which attaches content, so it needs tasks:write and content:write)files:read — files list / download-url, folder listingfiles:write — upload-url, folder mutationsskills:read — skills list / getautomations:read / automations:write — automation commands, including automation runWorkspace roles apply on top. Any member — including a viewer — can create and work tasks, but a viewer's tasks always require review (--no-review is ignored for them). Creating automations requires an admin; approving and publishing require a reviewer or admin. A 403/missing required scope error names what's missing — report it to the operator; do not retry.
failed or rejected, surface the reviewer's comment and the task id to the operator — do not silently retry more than once.