Pending prompts
Ready-to-paste prompts that agents (or you) leave for a future chat — handoffs, dated follow-ups — with reminders and one-click launch on a device.
A pending prompt is a complete, self-contained prompt saved for later: the handoff an agent writes when a goal is done, a follow-up that should only start after a date, or an idea you want to pick up in a fresh chat. It is stored centrally, so the same list shows up on the desktop app, the phone and the hub.
Agents read the list through the MCP server tools prompts_list (status, limit) and prompts_get (id). Both are read-only: launching a prompt starts a paid run, so it stays in the hub, desktop and phone.
Pending prompts: how agents leave prompts for later
- Capture. At the end of a goal the agent posts its "start a new chat with this" prompt to
POST /v1/prompts. The Copilot Stop hook, the desktop handoff tool, the phone and the hub all use the same endpoint, withsourcesaying which one. - Dedupe and supersede. The same text is stored once (a sha256 of the whitespace-normalised prompt), so two capture paths never create twins — the second call answers
200withcreated: false. Pass a stablegoal_keyand every older open prompt with that key becomessuperseded: only the latest handoff for a goal stays open. - Wait. Without
not_beforethe prompt is due at once. With a date (2026-10-01means 07:00 UTC that day) or an ISO datetime it stays quiet until then. - Remind. When
not_beforepasses you get aprompt.duenotification in the inbox (plus a push) whoseurliscodai://prompts/<id>. Withauto_run: truethe prompt is also launched automatically ontarget_device_id, or on your freshest desktop/Android device. - Act. Open the prompt and copy it, snooze it (
PATCHa newnot_before— this re-arms the reminder), mark itdone/dismissed, orPOST …/launch: that opens a new shared session and sends the text to a device as asendcontrol. The prompt moves tolaunchedand keeps therun_session_id.
import { Codai } from 'codai-sdk';
const codai = new Codai({ apiKey: process.env.CODAI_API_KEY! });
const saved = await codai.prompts.create({
prompt: 'Goal: finish the billing export…',
source: 'agent',
goal_key: 'billing-export',
not_before: '2026-10-01',
});
const due = await codai.prompts.list({ status: 'due' });
await codai.prompts.launch(saved.id);from codai import Codai
codai = Codai(api_key="codai_...")
saved = codai.prompts.create({"prompt": "Goal: finish the billing export…", "goal_key": "billing-export"})
codai.prompts.update(saved["id"], {"not_before": "2026-10-03"}) # snooze
codai.prompts.launch(saved["id"])Statuses: open → launched → sent → answered → verified, plus the closing states done / dismissed / superseded. GET /v1/prompts defaults to open; status=active returns everything still in flight (open, launched, sent, answered), status=due returns open prompts whose not_before is empty or already passed, status=all returns everything.
Sent, answered, verified
You do not have to mark a prompt by hand once you paste it into a chat:
- Sent. When a session reports a
turn_startwhose text matches an active prompt (same hash, same first 4 000 characters, or word overlap of at least 85 %), the gateway marks the promptsentand storesmatch_ref(the session) andmatch_turn_id. Clients that see chats the gateway does not (the VS Code extension scans local Copilot Chat sessions) report the same thing withPOST /v1/prompts/{id}/match. Matching never blocks or fails the turn. - Answered. When that turn ends (
turn_end), the prompt moves toanswered. - Verified.
POST /v1/prompts/{id}/verifyaskscodai-fastwhether the chat actually did what the prompt asked. It reads the session transcript, plus an optionaldiff(for examplegit diff base_sha..HEAD) andfilesfrom the client, and stores areport(verdictdone/partial/not_started,summary,changed,remaining). Adoneverdict moves the prompt toverified; any other verdict leaves the status alone.POST /v1/prompts/verifydoes the same for every active prompt that has a session (or for theidsyou pass). Every client has a Verify all button for this.
Live updates
GET /v1/prompts/stream is a server-sent event stream: one prompt event per create, update or delete of any of your prompts, so the desktop app, phone, hub and VS Code show the same state within a second or two. A backgrounded phone gets a push instead.
bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
status?stringFilter: a prompt status, active (open, launched, sent or answered), due or all.
"open""open""due""all""launched""done""dismissed""superseded""active""sent""answered""verified"limit?integerMaximum rows (1–200).
1 <= value <= 200100x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128Matching prompts.
application/json- response
data*array<>curl -X GET 'https://ai.codai.ro/v1/prompts'{ "data": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "title": "string", "prompt": "string", "status": "open", "source": "vscode", "repo": "string", "tracker": "string", "goal_key": "string", "not_before": "2019-08-24T14:15:22Z", "auto_run": true, "target_device_id": "12785743-1d27-41cd-88a7-0ac66360e3d6", "origin": {}, "notified_at": "2019-08-24T14:15:22Z", "launched_at": "2019-08-24T14:15:22Z", "run_session_id": "4b290cc7-5731-4ce8-8cd7-1bbbd88cfdb2", "done_at": "2019-08-24T14:15:22Z", "sent_at": "2019-08-24T14:15:22Z", "answered_at": "2019-08-24T14:15:22Z", "verified_at": "2019-08-24T14:15:22Z", "match_ref": "string", "match_turn_id": "string", "match_score": 0, "base_sha": "string", "head_sha": "string", "report": { "verdict": "done", "summary": "string", "changed": [ "string" ], "remaining": [ "string" ], "evidence": "transcript+diff", "model": "string", "at": "2019-08-24T14:15:22Z" }, "report_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" } ]}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
prompt*string1 <= length <= 32000title?string1 <= length <= 200source?PromptSource"vscode""cli""desktop""phone""agent""hub""manual""transcript"repo?stringlength <= 300tracker?stringlength <= 300goal_key?stringStable key of the goal; a new prompt supersedes older open ones with the same key.
1 <= length <= 200not_before?|ISO datetime with offset, or YYYY-MM-DD (07:00 UTC). null = due immediately.
auto_run?booleanLaunch automatically when due.
falsetarget_device_id?|uuidorigin?Free-form capture metadata (session, transcript, host).
The same text already existed; nothing was created.
application/json- response
A pending prompt. Timestamps are ISO strings or null.
id*stringuuidtitle*stringDefaults to the first line of the prompt (max 120 chars).
prompt*stringstatus*PromptStatus"open""launched""sent""answered""verified""done""dismissed""superseded"source*PromptSource"vscode""cli""desktop""phone""agent""hub""manual""transcript"repo*string|nulltracker*string|nullgoal_key*string|nullnot_before*|The prompt is due from this moment on.
date-timeauto_run*booleantarget_device_id*|uuidorigin*notified_at*|When the due reminder was sent.
date-timelaunched_at*|date-timerun_session_id*|uuiddone_at*|date-timesent_at*|When the prompt was seen sent in a chat.
date-timeanswered_at*|When the chat turn that carried it ended.
date-timeverified_at*|When a report first judged it done.
date-timematch_ref*|Session id or key the prompt was sent in.
match_turn_id*|Turn id of that chat turn.
match_score*|Match confidence, 0–1.
base_sha*|Repository HEAD when sent.
head_sha*|Repository HEAD at the last verification.
report*|Last verification report, or null.
report_at*|When report was produced.
date-timecreated_at*stringdate-timeupdated_at*stringdate-timecreated*booleanfalse when the same text already existed.
superseded*integerOlder open prompts with the same goal_key now superseded.
0 <= valuecurl -X POST 'https://ai.codai.ro/v1/prompts' \ -H 'Content-Type: application/json' \ -d '{ "prompt": "string"}'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "title": "string", "prompt": "string", "status": "open", "source": "vscode", "repo": "string", "tracker": "string", "goal_key": "string", "not_before": "2019-08-24T14:15:22Z", "auto_run": true, "target_device_id": "12785743-1d27-41cd-88a7-0ac66360e3d6", "origin": {}, "notified_at": "2019-08-24T14:15:22Z", "launched_at": "2019-08-24T14:15:22Z", "run_session_id": "4b290cc7-5731-4ce8-8cd7-1bbbd88cfdb2", "done_at": "2019-08-24T14:15:22Z", "sent_at": "2019-08-24T14:15:22Z", "answered_at": "2019-08-24T14:15:22Z", "verified_at": "2019-08-24T14:15:22Z", "match_ref": "string", "match_turn_id": "string", "match_score": 0, "base_sha": "string", "head_sha": "string", "report": { "verdict": "done", "summary": "string", "changed": [ "string" ], "remaining": [ "string" ], "evidence": "transcript+diff", "model": "string", "at": "2019-08-24T14:15:22Z" }, "report_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "created": true, "superseded": 0}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringPending prompt id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128The prompt.
application/json- response
A pending prompt. Timestamps are ISO strings or null.
id*stringuuidtitle*stringDefaults to the first line of the prompt (max 120 chars).
prompt*stringstatus*PromptStatus"open""launched""sent""answered""verified""done""dismissed""superseded"source*PromptSource"vscode""cli""desktop""phone""agent""hub""manual""transcript"repo*string|nulltracker*string|nullgoal_key*string|nullnot_before*|The prompt is due from this moment on.
date-timeauto_run*booleantarget_device_id*|uuidorigin*notified_at*|When the due reminder was sent.
date-timelaunched_at*|date-timerun_session_id*|uuiddone_at*|date-timesent_at*|When the prompt was seen sent in a chat.
date-timeanswered_at*|When the chat turn that carried it ended.
date-timeverified_at*|When a report first judged it done.
date-timematch_ref*|Session id or key the prompt was sent in.
match_turn_id*|Turn id of that chat turn.
match_score*|Match confidence, 0–1.
base_sha*|Repository HEAD when sent.
head_sha*|Repository HEAD at the last verification.
report*|Last verification report, or null.
report_at*|When report was produced.
date-timecreated_at*stringdate-timeupdated_at*stringdate-timecurl -X GET 'https://ai.codai.ro/v1/prompts/497f6eca-6276-4993-bfeb-53cbbbba6f08'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "title": "string", "prompt": "string", "status": "open", "source": "vscode", "repo": "string", "tracker": "string", "goal_key": "string", "not_before": "2019-08-24T14:15:22Z", "auto_run": true, "target_device_id": "12785743-1d27-41cd-88a7-0ac66360e3d6", "origin": {}, "notified_at": "2019-08-24T14:15:22Z", "launched_at": "2019-08-24T14:15:22Z", "run_session_id": "4b290cc7-5731-4ce8-8cd7-1bbbd88cfdb2", "done_at": "2019-08-24T14:15:22Z", "sent_at": "2019-08-24T14:15:22Z", "answered_at": "2019-08-24T14:15:22Z", "verified_at": "2019-08-24T14:15:22Z", "match_ref": "string", "match_turn_id": "string", "match_score": 0, "base_sha": "string", "head_sha": "string", "report": { "verdict": "done", "summary": "string", "changed": [ "string" ], "remaining": [ "string" ], "evidence": "transcript+diff", "model": "string", "at": "2019-08-24T14:15:22Z" }, "report_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringPending prompt id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
1 <= propertiestitle?string1 <= length <= 200prompt?string1 <= length <= 32000status?PromptStatus"open""launched""sent""answered""verified""done""dismissed""superseded"not_before?|ISO datetime with offset, or YYYY-MM-DD (07:00 UTC). null = due immediately.
auto_run?booleantarget_device_id?|uuidtracker?|length <= 300The updated prompt.
application/json- response
A pending prompt. Timestamps are ISO strings or null.
id*stringuuidtitle*stringDefaults to the first line of the prompt (max 120 chars).
prompt*stringstatus*PromptStatus"open""launched""sent""answered""verified""done""dismissed""superseded"source*PromptSource"vscode""cli""desktop""phone""agent""hub""manual""transcript"repo*string|nulltracker*string|nullgoal_key*string|nullnot_before*|The prompt is due from this moment on.
date-timeauto_run*booleantarget_device_id*|uuidorigin*notified_at*|When the due reminder was sent.
date-timelaunched_at*|date-timerun_session_id*|uuiddone_at*|date-timesent_at*|When the prompt was seen sent in a chat.
date-timeanswered_at*|When the chat turn that carried it ended.
date-timeverified_at*|When a report first judged it done.
date-timematch_ref*|Session id or key the prompt was sent in.
match_turn_id*|Turn id of that chat turn.
match_score*|Match confidence, 0–1.
base_sha*|Repository HEAD when sent.
head_sha*|Repository HEAD at the last verification.
report*|Last verification report, or null.
report_at*|When report was produced.
date-timecreated_at*stringdate-timeupdated_at*stringdate-timecurl -X PATCH 'https://ai.codai.ro/v1/prompts/497f6eca-6276-4993-bfeb-53cbbbba6f08' \ -H 'Content-Type: application/json' \ -d '{}'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "title": "string", "prompt": "string", "status": "open", "source": "vscode", "repo": "string", "tracker": "string", "goal_key": "string", "not_before": "2019-08-24T14:15:22Z", "auto_run": true, "target_device_id": "12785743-1d27-41cd-88a7-0ac66360e3d6", "origin": {}, "notified_at": "2019-08-24T14:15:22Z", "launched_at": "2019-08-24T14:15:22Z", "run_session_id": "4b290cc7-5731-4ce8-8cd7-1bbbd88cfdb2", "done_at": "2019-08-24T14:15:22Z", "sent_at": "2019-08-24T14:15:22Z", "answered_at": "2019-08-24T14:15:22Z", "verified_at": "2019-08-24T14:15:22Z", "match_ref": "string", "match_turn_id": "string", "match_score": 0, "base_sha": "string", "head_sha": "string", "report": { "verdict": "done", "summary": "string", "changed": [ "string" ], "remaining": [ "string" ], "evidence": "transcript+diff", "model": "string", "at": "2019-08-24T14:15:22Z" }, "report_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringPending prompt id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128How many prompts were deleted (0 or 1).
application/json- response
deleted*integer0 <= valuecurl -X DELETE 'https://ai.codai.ro/v1/prompts/497f6eca-6276-4993-bfeb-53cbbbba6f08'{ "deleted": 0}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringPending prompt id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
device_id?stringOne of your devices; overrides the prompt target.
uuidThe session that was started.
application/json- response
session_id*stringuuiddevice_id*stringuuidpushed*booleanWhether a push dispatch reached the device.
curl -X POST 'https://ai.codai.ro/v1/prompts/497f6eca-6276-4993-bfeb-53cbbbba6f08/launch' \ -H 'Content-Type: application/json' \ -d '{}'{ "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82", "device_id": "3bafab7b-4400-4bcf-8e6e-09f954699940", "pushed": true}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringPending prompt id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
ref*stringWhere it was sent: a session id or session key the client uses.
1 <= length <= 300turn_id?stringTurn id of the chat turn that carried the prompt.
length <= 300score?numberMatch confidence, 0–1.
0 <= value <= 1sent_at?stringWhen it was sent (defaults to now).
date-timeanswered?booleanThe turn already ended: move straight to answered.
base_sha?stringRepository HEAD when the prompt was sent.
length <= 100The updated prompt.
application/json- response
prompt*A pending prompt. Timestamps are ISO strings or null.
curl -X POST 'https://ai.codai.ro/v1/prompts/497f6eca-6276-4993-bfeb-53cbbbba6f08/match' \ -H 'Content-Type: application/json' \ -d '{ "ref": "string"}'{ "prompt": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "title": "string", "prompt": "string", "status": "open", "source": "vscode", "repo": "string", "tracker": "string", "goal_key": "string", "not_before": "2019-08-24T14:15:22Z", "auto_run": true, "target_device_id": "12785743-1d27-41cd-88a7-0ac66360e3d6", "origin": {}, "notified_at": "2019-08-24T14:15:22Z", "launched_at": "2019-08-24T14:15:22Z", "run_session_id": "4b290cc7-5731-4ce8-8cd7-1bbbd88cfdb2", "done_at": "2019-08-24T14:15:22Z", "sent_at": "2019-08-24T14:15:22Z", "answered_at": "2019-08-24T14:15:22Z", "verified_at": "2019-08-24T14:15:22Z", "match_ref": "string", "match_turn_id": "string", "match_score": 0, "base_sha": "string", "head_sha": "string", "report": { "verdict": "done", "summary": "string", "changed": [ "string" ], "remaining": [ "string" ], "evidence": "transcript+diff", "model": "string", "at": "2019-08-24T14:15:22Z" }, "report_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" }}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringPending prompt id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
transcript?stringChat transcript (max 40 000 chars).
length <= 40000diff?stringRepository diff since base_sha (max 40 000 chars).
length <= 40000head_sha?stringRepository HEAD the diff was taken at.
length <= 100files?array<string>Changed file paths.
items <= 500The updated prompt and the stored report.
application/json- response
prompt*A pending prompt. Timestamps are ISO strings or null.
report*LLM verification report of a prompt.
curl -X POST 'https://ai.codai.ro/v1/prompts/497f6eca-6276-4993-bfeb-53cbbbba6f08/verify' \ -H 'Content-Type: application/json' \ -d '{}'{ "prompt": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "title": "string", "prompt": "string", "status": "open", "source": "vscode", "repo": "string", "tracker": "string", "goal_key": "string", "not_before": "2019-08-24T14:15:22Z", "auto_run": true, "target_device_id": "12785743-1d27-41cd-88a7-0ac66360e3d6", "origin": {}, "notified_at": "2019-08-24T14:15:22Z", "launched_at": "2019-08-24T14:15:22Z", "run_session_id": "4b290cc7-5731-4ce8-8cd7-1bbbd88cfdb2", "done_at": "2019-08-24T14:15:22Z", "sent_at": "2019-08-24T14:15:22Z", "answered_at": "2019-08-24T14:15:22Z", "verified_at": "2019-08-24T14:15:22Z", "match_ref": "string", "match_turn_id": "string", "match_score": 0, "base_sha": "string", "head_sha": "string", "report": { "verdict": "done", "summary": "string", "changed": [ "string" ], "remaining": [ "string" ], "evidence": "transcript+diff", "model": "string", "at": "2019-08-24T14:15:22Z" }, "report_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" }, "report": { "verdict": "done", "summary": "string", "changed": [ "string" ], "remaining": [ "string" ], "evidence": "transcript+diff", "model": "string", "at": "2019-08-24T14:15:22Z" }}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
ids?array<>Your prompt ids to verify (max 20 are processed).
1 <= items <= 200all_active?booleanVerify your active prompts that have a session to read.
One result per processed prompt.
application/json- response
results*array<>curl -X POST 'https://ai.codai.ro/v1/prompts/verify' \ -H 'Content-Type: application/json' \ -d '{}'{ "results": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "ok": true, "verdict": "done", "error": "string" } ]}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128SSE stream (text/event-stream, cache-control: no-cache).
response?stringtext/event-streamcurl -X GET 'https://ai.codai.ro/v1/prompts/stream'"string"Last updated:
Triggers
Webhook triggers that turn GitHub, Sentry, monitoring or custom events into agent sessions, plus the notification inbox.
Scheduler
Scheduled agent tasks, terminal commands, webhooks and chains that run on any of your PCs, phones, watch or cloud VMs — cron or plain words, approvals, retries, failover and live run status.