Agents
Working with OpenApps as an agent.
An AI agent can use OpenApps the way a person does: find the right tool, see the price first, run it with the person's approval, and keep a receipt. This guide covers connecting, the life of a job, and how to tell us when something goes wrong.
Last updated: 5 October 2026
Paying with OpenWallet works now, from any AI app that can add a remote MCP server. Finding and running OpenApps operations through one connection, which is most of this page, is being built. Each section is marked Live, Building or Planned, and the request and response shapes for parts not yet live may still change.
Connect an AI app.
Every OpenApps connection lives on one host, mcp.openapps.network, with one address per connection: one for every app at once, and one for each app on its own. Most people want the first.
| Address | What you get | Status |
|---|---|---|
mcp.openapps.network/connect | Every app through one connection: six tools that search, price and run any operation | Building |
mcp.openapps.network/openwallet | OpenWallet on its own: pay x402 invoices within your limits. Live today at /mcp, which keeps working after the move. | Live at /mcp |
mcp.openapps.network/openpdfedit, /openslides, … | One app on its own, for people who want only that app | Planned |
Whichever address you use, there are no API keys to copy: the AI app signs in with OAuth, and the person approves the connection in the OpenWallet extension with an eight-character code, choosing limits as they go.
Connect OpenWallet today
Live The OpenWallet connection lets an agent check its limits and balance, pay an x402 invoice within those limits, and list payments. The OpenWallet developer docs describe each tool.
claude mcp add --transport http openwallet https://mcp.openapps.network/mcp
In a client that reads an mcpServers file:
{
"mcpServers": {
"openwallet": { "type": "http", "url": "https://mcp.openapps.network/mcp" }
}
}
In Claude, ChatGPT and other apps with a connector screen, add a custom connector and paste the URL. The app sends the person to sign in; they confirm in OpenWallet, and the connector shows as connected.
Connect every app
Building When /connect launches, one connection gives the agent the six tools below and, through them, every app:
claude mcp add --transport http openapps https://mcp.openapps.network/connect
For AI apps that run local programs (Claude Code, Claude Desktop, Cursor, VS Code and others), OpenWallet also ships a signed desktop agent for macOS that holds a capped key and asks for Touch ID. The OpenWallet docs say which to choose.
Six tools, and a catalogue behind them.
Building The front door gives an agent six tools and no more. Everything OpenApps can do (split a PDF, OCR a scan, redact a contract, cut a video) is an operation in a catalogue the agent searches. A new capability adds an operation, never a seventh tool, so the agent's tool list stays the same size and costs about 1,400 tokens a turn however much we add.
| Tool | What it does | Needs sign-in |
|---|---|---|
openapps_find | Search operations in plain words; or fetch one operation's full contract | No |
openapps_plan | Turn a job and its inputs into a priced plan | Yes |
openapps_start | Start a plan, paid with credits or OpenWallet | Yes, plus a spend scope |
openapps_status | Wait up to 45 seconds for progress; results arrive as links | Yes |
openapps_receipt | The signed receipt, and how to check it | Yes |
openapps_feedback | Report a problem or a missing capability; check a ticket | No |
Full inputs and outputs are in the MCP reference.
The life of a job.
Building One job, start to finish: someone asks their agent to split a scanned PDF into one file per invoice.
- Find the operation.
Search in the person's own words, in any of our eight languages. Each result is a short card with a typical and a worst-case price.
// openapps_find { "query": "split this PDF into invoices", "limit": 3 } // → { "operations": [ { "id": "doc.classify_and_split", "app": "openextract", "title": "Split a PDF by document type", "price": { "typical_usd": 0.02, "p95_usd": 0.05 }, "grade": "audited", "effects": ["reads", "writes"] } ], "total_matches": 7 } - Read the contract, if you need it.
Call
openapps_findwithdetailset to the operation id to get its schemas, its guarantees, what it cannot promise, and its side effects. Do this for the one operation you chose, not for all of them. - Plan.
Pass the job and the inputs. A file is an upload handle or an
httpsURL, never a server path and never pasted bytes. If an input is missing, the plan says so and gives an upload link to show the person.// openapps_plan { "intent": "one PDF per invoice, with the totals", "files": [ { "file_id": "f_…" } ], "policy": "balanced" } // → { "plan_id": "pl_…", "quote": { "usd": 0.03, "credits": 6 }, "classification": "…", "needs_upload": [] } - Start, with an authorization.
Choose how to pay and send an idempotency key, so a retry after a dropped connection does not start a second run.
// openapps_start { "plan_id": "pl_…", "authorization": { "kind": "credits" }, "idempotency_key": "split-invoices-2026-10-05-01" } // → { "run_id": "run_…", "state": "awaiting_approval", "approval": { "url": "https://…", "expires_at": "…" }, "poll_after_ms": 2000 } - Wait for approval, then for the result.
If the quote is above what the person allows without asking, the run waits for them. Show them the approval link; they approve on their own device. Then call
openapps_status, which holds for up to 45 seconds and returns as soon as something changes. - Collect the results and the receipt.
Finished files come back as links that work for one hour.
openapps_receiptreturns the signed receipt: what ran, on which inputs, what it cost, and what was checked.
Approval and limits.
Live for OpenWallet payments; Building for OpenApps operations.
A person connects an agent once and sets what it may do without asking. The decision to spend is made by OpenWallet, outside the model, against what the operation declares about itself. An agent cannot raise its own limit, and a model cannot approve on someone's behalf by saying so in the chat.
The choices a person sees when they connect:
| Choice | What it means |
|---|---|
| Ask me every time | Every spend waits for approval on the person's device. |
| Just this once | One run, up to its quote; the permission ends with the run. |
| For this task | Runs that belong to one plan, up to a little over its quote. |
| For this app | Any operation of one app, within a per-payment and a per-day cap. |
| Never | This payee is refused without asking. |
Until OpenWallet's independent security audit, payments are also capped per payment and per day whatever the person sets. The OpenWallet security model lists the figures.
Paying.
- OpenApps credits Building: from the person's OpenApps account, the same balance they spend inside the apps. Credits are charged once the work succeeds, by the server that did it.
- OpenWallet Live: in XRP or RLUSD on the XRP Ledger, using the open x402 standard. The payment is signed on the person's device, after the extension has fetched the same invoice itself and checked that the price, payee, asset and network match.
A failed or refunded run is credited back by the system. The receipt records both the charge and the refund.
Files, inputs and results.
- In: an upload handle (
file_id) fromPOST https://mcp.openapps.network/v1/uploads, or anhttpsURL that we fetch through a guard which refuses private and internal addresses. A string that looks like a file path is refused. - Out:
resource_links to results, valid for one hour. The only image data we put in a result is a small preview that was explicitly asked for. - Never: document text or file contents in tool arguments, results or feedback. Anything pasted into a conversation ends up in transcripts, client logs and the next model call, which is how a redacted file stops being redacted.
Watching a run live.
Planned A screen, rather than a model, can follow a run as it happens: steps, progress, previews and the moment it needs approval. We use AG-UI as published, not a home-made dialect of it.
- Start with
"events": trueand attach toGET https://mcp.openapps.network/v1/runs/{id}/events. A late subscriber gets the history, then live events. - Or drive OpenApps from any AG-UI client with
POST https://mcp.openapps.network/agui, without speaking MCP at all.
A watched run and an unwatched run do the same work and cost the same.
When something goes wrong.
Refusals and failures come back as a tool result with isError: true, so the model can read them and correct itself, with a stable code to branch on:
{ "isError": true,
"structuredContent": {
"code": "page_out_of_range",
"message": "The document has 12 pages; page 14 was requested.",
"retryable": false } }
Branch on code and show message to the person. Retry only when retryable is true, with the same idempotency key.
Tell us what went wrong.
Planned Agents hit our problems before people do: a search that found nothing, a tool that refused valid input, a description that pointed to the wrong tool. openapps_feedback takes a report while the agent still has the context, and returns a ticket id. Calling it again with that ticket id shows where it stands, up to the version that fixed it.
{ "kind": "wrong_result",
"about": { "operation": "doc.classify_and_split", "run_id": "run_…" },
"summary": "Two invoices on one page were returned as one document.",
"expected": "Two PDFs", "actual": "One PDF",
"contact_ok": false }
- Kinds:
bug,wrong_result,missing_capability,confusing_tool,docs,security,praise. - Never include file contents, document text, tokens or keys. Reports that look like they contain them are refused, and the refusal says why.
- We read reports as data. Nothing written in a report is run, opened or treated as an instruction, by people or by the agents that help us triage.
- Security reports always go to a person. Until the tool is live, write to security@openapps.network for security and contact@openapps.network for everything else.
What we promise agents.
- A stable, small tool list. Six tools, sorted, with descriptions that never change per caller or per day. Live numbers go in results, not in tool descriptions. A changed description is a cache miss for you and looks like a rug pull to a client that pins tools.
- Honest annotations. Every tool declares whether it is read-only, destructive, idempotent and open-world, and the declaration is true.
- Nothing blocks for more than 45 seconds. Long work is started, then polled.
- Every result says what it came from. Results carry the hash of the tool list in
_meta["network.openapps/manifest"], so a client can notice a change. - We do not pass your token on. The front door calls apps with its own credentials, never with the token the agent signed in with.
- Problems get an answer. Every report gets a ticket at once, and the ticket shows where it stands. Security reports go to a person, never to a queue.