Using plori from an agent
If you were asked to set up plori, follow Connect below: add the plori MCP server to this client, have the account owner sign in, and confirm the tools respond before you report success.
Plori runs AI agents in cloud Workspaces. Several agents can work on one project at once, and
Plori merges their changes back into the Workspace. A Workspace holds a project's files under
/workspace, saved versions of those files, a main conversation and the run history.
Connect
If this client already lists Plori tools and list_workspaces answers, skip this section.
MCP: Streamable HTTP at https://api.plori.ai/mcp.
- OAuth 2.1: an unauthenticated request returns 401 with the discovery chain (RFC 9728 metadata at https://api.plori.ai/.well-known/oauth-protected-resource, dynamic client registration, authorization code + PKCE). The account owner signs in with an email code.
- API key: the account owner creates one at https://plori.ai. Send
Authorization: Bearer plori_sk_....
Claude Code: connect from this conversation
Read these instructions in the current conversation before starting authentication.
Installing a skill or plugin is optional. Use this flow only in interactive Claude Code
when its Plori MCP client exposes both authenticate and complete_authentication.
Other clients use their ordinary OAuth or API-key setup above.
If this Claude Code build does not expose both authenticate and
complete_authentication, use /mcp instead. Pick plori, choose Authenticate, then
sign in with the emailed code. If the browser cannot reach the localhost callback,
Claude Code prompts for it directly in its own dialog, never in chat. Then verify with
list_workspaces.
- Check the current MCP configuration and active tools. Reuse an existing Plori server
at
https://api.plori.ai/mcp; do not add duplicate entries or replace a different server with the same name. If missing, configure it once withclaude mcp add --transport http plori https://api.plori.ai/mcp. Confirm the server is available in this conversation before authenticating. Saving configuration alone does not prove that it loaded. If its tools are missing, ask the user to type/reload-pluginsin this Claude Code conversation, then resume these steps in the same session. This also refreshes MCP configuration when no plugins are installed. It is a user command; do not try to invoke it through the Skill tool. Confirm the authentication tools are available before proceeding. If they are still missing, use/mcpinstead (above). - If Plori tools already work, the connection is complete. Otherwise, call the
client's Plori
authenticatetool using its exposed schema. Keep the returned authorization URL intact. Do not construct a new OAuth request or change its state, redirect URI, or PKCE challenge. - POST JSON
{"authorization_url":"<the exact client URL>"}once tohttps://api.plori.ai/oauth/pair. The response containsuser_code,verification_uri,verification_uri_complete,device_code,expires_in(seconds), andinterval(seconds). Keepdevice_codeprivate. If a permission rule, hook, or tool denies this request, stop and use the fallback below. - Tell the user: "Open <verification_uri> and enter <user_code>. Sign in and approve the connection; I will continue when you finish." The user can open the page on their phone. Display the short address and code, not the authorization or callback URL. Do not ask the user to copy a callback URL into chat.
- Poll
https://api.plori.ai/oauth/pair/pollwith JSON{"device_code":"<device_code>"}. Keep only one request in flight, allow each request at least 30 seconds to finish, and wait at leastintervalseconds between requests. The server can hold a pending request for 25 seconds. Read pending and failure responses from the JSONerrorfield, notstatus. Onerror: "authorization_pending", continue. Onerror: "slow_down", use the larger of your previous delay plus five seconds and the response'sintervalfor all subsequent requests. HonorRetry-Afterwhen present on HTTP 429. On HTTP 503 witherror: "temporarily_unavailable", preserve this pairing and the pending client authentication. Wait at least the larger of your poll interval andRetry-After(five seconds), then retry the same device code. A temporary failure does not extendexpires_in; retry only within the original four-minute window while the client authentication remains pending. If a permission rule, hook, or tool denies a poll request, stop and use the fallback below. - On
status: "approved", pass the returnedcallback_urldirectly to the same client'scomplete_authenticationtool using its exposed schema. Do not navigate to the loopback URL or exchange the code yourself: the client owns the PKCE verifier. Then discover Plori tools and calllist_workspacesto confirm the connection before reporting success. This verification does not create a Workspace or start paid work.
Fallback when a pairing request is denied
Use this fallback after the first permission, hook, or tool denial of either pairing
POST. Do not make another request to /oauth/pair or /oauth/pair/poll, and do not
try curl, wget, WebFetch, Python, a shell script, or another generic network
tool.
- Show the user the exact authorization URL returned by the current
authenticatecall. Ask them to open it in their browser, sign in, and approve the connection. Do not edit the URL. - After approval, the authorization server redirects the browser to a localhost callback. If that redirect connects, let the client finish authentication. If the browser cannot connect to localhost, ask the user to copy the final localhost callback URL from the browser address bar and paste it into this conversation. It contains one-time authorization data, so tell the user not to paste it anywhere else. Do not ask for that URL before the redirect has failed.
- Pass a pasted callback URL only to the same client's
complete_authenticationtool. Do not open, fetch, rewrite, log, or exchange it yourself. - Discover Plori tools and call
list_workspacesbefore reporting success. This check does not create a Workspace or start paid work.
If the authorization URL or pending client authentication expires during this
fallback, discard it and call authenticate again. Use only the new authorization
URL. Never reuse an expired URL.
Stop on access_denied; do not retry a denied request automatically. On
expired_token, an already-consumed pairing, or a client authentication timeout,
start a fresh client authentication before creating another pairing. Never reuse the
old authorization URL. Pairing lasts four minutes to fit within the client's pending
login. If the approved response is lost, restart the whole flow; the callback is
returned only once. Keep approval polling active while the user signs in.
Remote Control can use this flow only when it controls that same interactive Claude Code process and the two authentication tools are available. A separate hosted Claude.ai connector or Agent SDK session needs its own supported authentication flow. URLs can still appear in client tool results; do not promise to hide tool transcripts.
Switch accounts or sign out
To connect a different Plori account or sign out, use /mcp. Pick plori, choose Clear
authentication, then Authenticate again with the new account's email code.
claude mcp remove does not clear the stored token.
CLI and REST
CLI: curl -fsSL https://plori.ai/install.sh | sh (Windows: irm https://plori.ai/install.ps1 | iex),
npm i -g @plori/cli, or npx -y @plori/cli. The shell installer writes to
~/.local/bin and edits no rc file, so run export PATH="$HOME/.local/bin:$PATH" first.
plori login signs in through the browser; headless callers use
plori login --key plori_sk_... or set PLORI_API_KEY. Piped output and --json give
JSON.
REST: https://api.plori.ai/v1 with the same bearer token. Detail: https://plori.ai/auth.md
Tools
The MCP server has 24 tools. Invitees use their own login, API keys and OAuth sessions. Workspace calls resolve access to the owning account from the resource.
Workspaces
list_workspaceslists your own and shared Workspaces withaccount(user_id,email) and yourrole(owner,memberorviewer). Passworkspace_idfor one.storage_readinessis present while its storage starts.create_workspace(name,idempotency_key) returnsidanddefault_agent_id, the Workspace's agent. Withoutdefault_manager_agent_idit creates that agent, which counts against the agent limit. Optionalaccountselects a shared account by user id. Omit it for your own account. Members can create there. Viewers cannot. The result includesaccountandrole. Names are not unique: reuse a Workspace.delete_workspacepermanently deletes its files, saved versions, copies and conversations.get_creditsreturns the balance. Check it before long work.
Send a task
send_workspace_message (workspace_id, message) runs a task in the Workspace's main
conversation, or in the one named by session_id. Use it for most work, including work
that can be split: the Workspace's own agent splits it between several agents, merges their
changes and fixes conflicts.
- For a new or continued run, the call holds until the run ends, pauses for input, or the hold ends. The server picks a hold that fits your client. Use that default.
- If the result is
running, callget_run_result(workspace_id,run_id) afterpoll_after_seconds. Repeat until the run completes or isawaiting_input. get_run_result,cancel_run,list_runs,list_pending_inputsandschedule_runtake theworkspace_id.- Reuse
session_idto keep context. An idle conversation starts a run. While running, plain text returnsstatus: "steering"or"queued"withsteer_id. - If the paused run has exactly one ordinary question assigned to you, your message
answers it. Otherwise it queues, and
pending_inputsnames the request and assignee. A message never cancels a pending request. If the result hasstatus: "answered"andcontinuation_pending: true, read the paused run until it reportscontinuation_run_id. Do not submit the answer again. - A queued or steering receipt returns immediately, regardless of
wait. It includesrun_id,session_id,agent_id,workspace_id,urlandpoll_after_seconds. Itsrun_idis the running or paused run, not a result for this message. Uselist_runsto find a later queued turn. No lookup connectssteer_idto that run. - 409
conversation_busystill applies to attachments or run options in a busy conversation, and to working-copy conflicts. Send attachments and options when idle. - A retry with the same
idempotency_keyreturns the original run or message receipt for 24 hours.max_turn_tokenssets an optional token ceiling for the turn.cancel_runstops a run.
Files
- Only files under
/workspacepersist between runs. Software installed elsewhere and processes a run starts do not. UseTMPDIRfor temporary files. - A completed run does not prove its files are saved: wait for
file_source.statereadywith nosave_failure. - A completed run's
filesare URLs readable with the same bearer token.read_workspace_filereads a saved version:current_revision, an agent'ssaved_revision_id, or a changeset'sbase_revision,incoming_revisionorresult_revision. A path such as/workspace/a.mdis not a URL. upload_workspace_filewrites a file into the Workspace's current files. Pass text up to 262144 bytes ascontent. For a larger or binary file (up to 32 MiB), omitcontentand run the returnedcurlcommand in a shell within 10 minutes. Its URL accepts one upload.
Approvals and questions
- A run started through MCP or a schedule pauses before each action outside the Workspace (connected-account and MCP writes, outbound HTTP writes, git push, publishing, deploys, email, public tunnels, irreversible browser actions, workflow activation) until the account owner approves that one action in the Plori web app.
awaiting_inputis an approval or a question. Show it to the human, with the approval'sapprove_url.- You cannot approve or grant
always_allow.answer_pending_inputcan only deny a request or answer a question. Never send secrets through it. - Then follow the
continuation_run_idfromget_run_result.answer_pending_inputreturns the continuation'srun_id, orcontinuation_pending: truewhile files save; then poll the paused run untilcontinuation_run_idis set. list_pending_inputsis the current queue; an old run can keepawaiting_input. Aconsent_toolrow is an outward write: only the human approves it or grants standing consent, in the web app.- Requests go to the worker's creator, or to the owner for the manager. The owner can
also answer a worker's request. Other members can read it and may answer after the
account's timeout, 30 minutes by default. Viewers never answer. Standing grants and
secret answers stay owner-only.
list_pending_inputsincludesassigned_to,open_to_members_atandcan_actfor the caller. Credential restrictions still apply. - A member's monthly spend cap can refuse a new run with 402. Schedules, previews, workflows, Workspace settings and deletion are owner-only in M1.
- Clients with the MCP Tasks extension get a task handle instead. A returned call does not report later changes: poll, or keep a subscription.
Scheduled runs
schedule_run (workspace_id, prompt, delay_seconds or an RFC3339 fire_at) returns
status: "awaiting_confirmation" and a confirm_url. Show the human the prompt, the time
and the confirm_url. The run is queued only after the owner confirms in the web app.
Run several agents yourself
Only for a client that manages the agents itself. Each agent works on its own copy of the files. Plori submits changed files when a run completes normally and accepts a clean comparison.
create_workspace_worker(workspace_id,task,idempotency_key) returnsagent_idandtask_group_idat once; the agent queues while capacity is busy. Passtask_group_idto later calls to group their costs and stop request;get_workspace_costsreports cost. Worker agents do not count against the agent limit.- Poll
get_workspace_workerorlist_workspace_workersuntilsave_stateisready.get_run_result(run_id,workspace_id) reads the reply and approval requests.steer_workspace_workermessages a running turn (409run_not_runningif it has not started, is paused or has ended).cancel_runstops one agent,stop_workspace_task_groupa group. - Check
get_workspace_worker(change_status,changeset_id), thenget_workspace_changeset. Usesubmit_workspace_changesetonly for saved, unsubmitted work after an error, cancellation or stop, or afterrecompare_required. - Poll
get_workspace_changeset:acceptedwithresult_revisionconfirms the files landed.needs_resolution: ask the Workspace's agent to combine files withsend_workspace_message, or reject and start another worker. - For
review_ready,accept_workspace_changesetcompletes the merge (expected_current_revision= thecomparison_current_revision;validation_evidence= 1-32 short statements of the checks you made).reject_workspace_changesetdiscards it. After accept, poll untilstateisacceptedandresult_revisionis set.
Accept errors:
- 409
current_revision_conflict: another merge landed first. Submit again, then repeat steps 4 and 5. - 409
workspace_changeset_unresolved: not computed yet, or it has conflicts. A merge with conflicts cannot be completed through MCP. To have conflicts fixed, send the task to the Workspace withsend_workspace_message; its agent fixes conflicts. - 409
workspace_changeset_busy: a run or file operation is active. Accept after it ends.
These agents pause before outward actions like other runs. Workflows, usage and disk reports, trash and connected accounts are not on MCP; use the web app, REST or the CLI.
Workspace CLI commands
The CLI also covers what MCP does not. Use exact IDs; there is no implicit active Workspace.
Groups: workspace, independent-agent, copy, revision, workspace-files,
worker, task-group, changeset, operation; plori GROUP --help lists actions and
flags. Commands that create something take --idempotency-key KEY. To complete a merge:
plori changeset accept WORKSPACE_ID CHANGESET_ID --current-revision REVISION_ID --evidence TEXT --idempotency-key KEY with the comparison_current_revision. Writes to a
copy need the --if-match ETag you read. Use --yes (agent-retire,
workspace delete) only when the human authorized the action. Examples:
https://plori.ai/docs/cli
Long runs
Use the default wait. If the result is running, call get_run_result after
poll_after_seconds, until the run completes or is awaiting_input.
Troubleshooting, optional: if your client drops the results of long calls, pass
wait_seconds with a shorter hold, or wait=false. In Codex, tool_timeout_sec on the
plori entry in config.toml sets how long a call can last. plori watch in a background
shell prints run endings and input requests.
CLI commands
Agents are addressed by name or ID. Every command accepts --json.
plori run <name> "message"waits for the reply;--no-waitreturns a run ID.plori result <name> <run-id> --wait(bounded by--wait-seconds) reads the result.plori watchprints run endings and input requests as JSON lines.plori inboxlists what ended and what waits on you.plori inputs <name>;plori answer <run-id> <tool-call-id> --approve|--deny|--value <v>. Add--always-allowonly on the human's explicit instruction.plori schedules create <workspace> "prompt" --in <seconds>(or--at <rfc3339>).plori attachis for a human at the keyboard; an agent uses--read-onlyto tail.
Exit codes of run, result --wait and watch: 0 succeeded, 1 API or runtime failure,
2 usage error, 3 credentials missing, rejected or expired, 4 control plane unreachable, 10
awaiting human input, 20 run error, 30 cancelled, 40 wait ran out with the run still going.
Costs and limits
Runs spend credits. The plan sets included credits, disk, agent count, workflow limits and
the length of one run. Registered accounts have no limit on concurrent agent runs.
Anonymous trials allow at most 2 concurrent agent runs across their agents.
A third run makes send_workspace_message return 429 with advice to register free.
Registered accounts have no token ceiling per turn unless max_turn_tokens sets one.
max_turn_seconds sets a turn's time budget.
More
- Integration entry point: https://plori.ai/agents.md
- MCP connect guide: https://plori.ai/mcp
- CLI on npm: https://www.npmjs.com/package/@plori/cli
- Authentication detail: https://plori.ai/auth.md
- Site map for agents: https://plori.ai/llms.txt
