SchemAgentic

Services

A service is how a node reaches something outside the schema. It is the only way an agent can reach anything at all — and it is deliberately narrow: a fixed address, a fixed list of operations, a credential the app can never read back, and a person standing in front of anything that matters.

What a service is

A service belongs to a node. It has an address, a way of authenticating, and a list of operations — the specific things it can do, each with a name and the parameters it takes. An agent on that node may call those operations and nothing else. It cannot compose a URL, cannot call an operation nobody declared, and cannot reach a service on a different node.

There are three ways to get one:

The catalogue

These are built in. Choosing one of them is always better than describing the same API yourself: the address and the operations are ours to keep right, and the rules that make them safe travel with them.

In the app, the catalogue is grouped by what each family is for, and there is a search — look for "refund", "send an email" or "text message" rather than for a product name.

Stripe — Payments

Take and refund payments, and read what has been paid. Needs a Stripe secret key (sk_test_… or sk_live_…). Read Payments before using it.

OperationWhat it does
Check the balanceWhat is available and pending.read
List recent paymentsThe most recent payments, newest first.read
Look up one paymentOne payment by its id.read
Take a paymentCharges an amount.moves money
Refund a paymentGives money back, in whole or in part.moves money

Slack — Messaging

Read a channel and post to it. Needs a Slack bot token (xoxb-…) from your app's OAuth & Permissions page, invited to the channels you want.

OperationWhat it does
List channelsThe channels this token can see.read
Read a channelThe most recent messages in one channel.read
Post a messageSays something in a channel, as the app.messages people

GitHub — Code

Read issues and pull requests, open issues, and comment. Needs a personal access token (github_pat_… or ghp_…) with access to the repositories you name.

OperationWhat it does
List issuesIssues in a repository, filtered by state or label.read
Look up one issueOne issue, with its body and state.read
List pull requestsPull requests in a repository.read
Open an issueOpens a new issue.messages people
Comment on an issueAdds a comment to an issue or pull request.messages people

Opening an issue and commenting both notify everyone watching, which is why they are treated as messaging people rather than as ordinary writes.

Resend — Email

Send email from a domain you have verified with Resend. Needs a Resend API key (re_…).

OperationWhat it does
Send an emailOne email, from a verified sender.messages people
Look up a sent emailWhat happened to one email that was sent.read

Twilio — SMS

Send a text message. Needs your Account SID and Auth Token as one line separated by a colon: AC…:your_auth_token. Every message Twilio sends is charged to your Twilio account.

OperationWhat it does
Send a text messageOne SMS to one number.messages people
List recent messagesWhat has been sent and received recently.read

Twilio charges per message, but an SMS has no amount for us to check, so the spending limits do not apply to it. Every send still needs a person to approve it — that approval is the only thing standing between a mistaken instruction and a phone bill.

Notion — Documents

Search and read pages and databases. Read-only: nothing here writes to your Notion. Needs an internal integration secret (ntn_… or secret_…), shared with the pages you want it to see.

OperationWhat it does
SearchFinds pages and databases the integration can see.read
Read a pageOne page's properties.read
Read a page's contentThe blocks that make up a page.read
Query a databaseThe rows of one Notion database.read

Airtable — Data

Read and write rows in an Airtable base. Needs a personal access token (pat…) with access to the base.

OperationWhat it does
List rowsRows from a table, optionally filtered by view or formula.read
Look up one rowOne row by its id.read
Add a rowAdds one row.needs approval
Change a rowChanges the columns you name, leaving the rest alone.needs approval
Delete a rowRemoves one row for good.deletes data

Google Calendar — Calendar

Read what is in a calendar and add events to it. There is nothing to paste: you sign in at Google and it hands the access to our server — see Signing in.

OperationWhat it does
List calendarsThe calendars this account can see.read
What is coming upEvents in a calendar, soonest first.read
Look up one eventOne event by its id.read
Add an eventPuts something in the calendar; anyone invited is emailed.messages people
Remove an eventCancels an event for good.deletes data

Adding one

  1. Select a node and open its toolbar.
  2. Choose the service icon. If the schema is not in the cloud yet it is moved there first — services are called from a server.
  3. Pick a family, search the catalogue, describe an API, or type an address yourself.
  4. Give it a name, then add its credential.
  5. Use Try it now on a read-only operation to check the connection before an agent depends on it.

Services are part of the paid plan: 25 on Pro, 125 on Pro Max, per account. They run on the schema owner's plan, and every call is metered.

Credentials

A service's key is the one thing this app holds and never keeps. When you paste one it goes straight to a server, which stores it in Google Secret Manager — outside the database, where no client can read it.

Clearing the box and saving removes the credential. Some families have no box at all — see Signing in.

Signing in, instead of pasting a key

Most of what people actually want a node connected to — a calendar, a mailbox, a drive — does not hand out pasteable keys at all. For those, the service's screen offers Sign in rather than a box to type into:

  1. Choosing it opens the provider's own sign-in page in your browser. The link is one-time and expires in ten minutes.
  2. You sign in at the provider — never here — and it asks whether SchemAgentic may act for you, listing exactly what it would be allowed to do.
  3. The provider hands the access straight to our server, over a channel your browser never sees. The app never holds it, even for an instant.

From then on it works like any other service. The access is renewed automatically before it expires; if it is ever revoked — you changed your password, or withdrew it at the provider — the service says so and asks you to sign in again, rather than failing quietly.

Sign out destroys what is held. Nothing is left behind, and the service goes back to having no credential at all.

What needs a person

An agent must have a person approve, in that run, any operation that:

KindWhat it coversExtra rules
moves money Taking a payment, refunding one. Also needs a spending limit, and cannot be run from Try it now at all.
messages people Email, SMS, a Slack post, opening or commenting on an issue. The agent is told to say who will receive it and what it will say.
deletes data Removing a row or record. The agent is told to say exactly what would be removed.
changes data Any other write — adding or changing a row. Marked by the family, or by whoever declared the operation.

For a family, what an operation counts as is ours to decide, not the definition's. Editing a service document to claim that taking a payment is read-only changes nothing: the family's answer wins, every time.

An approval covers that exact operation in that run — see Approvals.

Payments

A payments service is the one that can cost you real money, so it has rules of its own on top of everything above.

Test mode and live mode

Every payments service starts in test mode, pointed at the sandbox. Its key has to match its mode: a live key in a test service is refused, and so is a test key in a live one. Switching to live asks you to confirm, because from that moment payments are real.

Limits are required, not optional

A payments service may spend nothing at all until someone sets two limits on its screen: the most it may spend at once, and the most it may spend in a month. Until both are set, every payment is refused and the agent is told so up front, so it says a limit needs setting rather than proposing a payment that would bounce.

Why it works this way round. If an unset limit meant "no limit", the most dangerous service in a schema would be the one nobody had finished setting up. So an unset limit means nothing may be spent, and spending is something a person switches on deliberately.

Amounts are typed the way you think about money — 50 or 49.99 — and both ceilings are kept consistent: a per-payment limit is never left above the monthly one. The running total is shown next to the monthly limit and resets at the start of each month.

What has been spent is the server's count

The total a service has spent this month is written only by the server. Nobody can edit it — not an editor, not the owner, not an agent. A limit you can raise is a decision; a counter you can reset would make the limit meaningless.

A retried run cannot charge twice

Every payment carries a key derived from the run that asked for it, the operation and the exact amount. If the same run is retried after a network failure, the payment provider recognises the same key and does not charge again. It is derived rather than random precisely so that a retry is not a new payment.

Try it now cannot spend

Try it now refuses money-moving operations outright. Checking a connection is not the same as spending, and a payment should only ever happen down the path that records who approved it.

The built-in service is the only way in

A service you describe yourself cannot be pointed at a payments API we have a family for. It would reach the same endpoints with none of what makes payments safe — no limits, no protection against paying twice, no test/live check — so that route is closed, for drafted and hand-typed services alike.

AI-drafted services

For anything not built in, describe it — "the OpenWeather current weather API" — and a definition is drafted: an address, and the operations it believes that API has, with their parameters.

A draft is a proposal, not a service. Nothing is saved until you read it and press save. That step is the point: what comes back is a guess about somebody else's API, and you are the one who can tell whether it is right. Check the operations against the API's own documentation before you rely on them.

Before you are shown a draft, the server checks it:

Drafting uses the model, so it counts against the owner's monthly allowance like an agent's thinking does.

Describing an API yourself

Choose Type an API address myself, give the service a name and an https:// address, then add operations one at a time. For each: a name, a method, and a path. Use {braces} for parts of the path that are filled in per call.

Anything that is not a GET is treated as changing data by default, so an agent has to ask before calling it. You can change that on the operation's screen — do it only for an operation you are certain is a read.

Authentication can be none, a bearer token, an API key in a header you name, or a username and password. The credential itself is stored the same way as any other, and is equally unreadable afterwards.

Receiving from outside

Everything above is the schema reaching out. A service can also be given an address the outside world posts to — Stripe saying a payment arrived, GitHub saying an issue was opened, a machine posting a reading. Choose Receive from outside on the service's screen; what arrives lands on the node's input, and its agents can be run with it.

An address anyone on the internet can post to is a different kind of thing from a call you make, so:

Making a new address replaces the old one, which stops working immediately. Stop receiving removes it and destroys the signing secret.

Connections held open

A webhook waits to be called. Some things do not work that way at all: an MQTT broker, a websocket feed and a server-sent event stream all push whenever they have something, down a connection that has to stay open. Those run on a separate always-on service, and a node can subscribe to one.

On the service's screen, set its transport and address:

TransportAddressAfter a reconnect
Server-sent eventshttps://…Resumes from the last event id the server gave it, so nothing between is lost.
WebSocketwss://…Starts from now. A websocket has no standard way of saying what you missed, and we do not invent one.
MQTTmqtts://… plus topicsThe broker keeps your session and delivers what queued while you were away.

An unencrypted address is refused: the credential travels on that connection. So is an address inside a private network, for the same reason a call to one is.

What arrives lands on the node's input exactly as a webhook would, and can run the node's agents. The same caps apply, plus two that only a stream needs:

A stream costs while it is held open, not per message, so it needs a subscription the way an agent does — and when one lapses, streams are closed, never deleted. They start again by themselves when the subscription does.

Kafka and AMQP are not available yet. They are in the design, and a service asking for one is simply not a stream rather than a stream that connects to nothing.

Watching for a change

Where an API has neither a webhook nor a stream, a service can poll it — call a read-only operation on a schedule and deliver only what is new.

Every rule a call passes

In order, every time, for every call — whether it came from an agent or from Try it now:

  1. The operation must exist on that service. For a family, the operations are the family's, so a document cannot invent one.
  2. The address is the family's, where there is one. It is not a field anyone can point elsewhere.
  3. The URL must be https, with no credentials in it.
  4. The host is resolved and every address it resolves to is checked. Anything private — 10.x, 127.x, 192.168.x, 169.254.x and the rest — is refused. This is checked again on every redirect, because a public host is free to redirect to a private one. At most three redirects.
  5. Money operations: limits must be set, the amount must be within both of them, and the key must match test or live.
  6. Anything sensitive or data-changing must have been approved, for that exact operation, in that run.
  7. The credential is added to the request's headers, and only there.
  8. The call is given 10 seconds and at most 64 KB of reply.
  9. The reply is redacted of anything matching the credential before it is recorded or shown.
  10. The call is metered, and the service's health and last error are updated.

Only GET, POST, PUT, PATCH and DELETE are allowed. An agent may make at most 8 service calls in one run.

Who can change what

FieldOwner / editorViewerServer
Name, operations, address, limits, test/liveYesNo—
The credentialWrite only, never readNoReads it for a call
Health, last error, call countNoNoYes
What has been spent this monthNoNoYes

When something goes wrong

What you seeWhat it means
"This service has no key yet"Add its credential on the service's screen.
"That does not look like a … token"The key is for the wrong service, or truncated. Each family knows the shape of its own.
"This service is set to test, but that is a LIVE key"Either switch the service to live, or paste a test key. The two must agree.
"Nobody has said what this service may spend"Set both spending limits on the service's screen.
"That is more than this service is allowed to move in one go"The amount exceeds the per-payment limit. Raise the limit deliberately, or have the agent propose less.
"That would put this service over what it may move this month"The monthly ceiling would be crossed. It resets at the start of the month.
"This operation moves money. It can only be run by an agent, with a person's approval."Try it now will not spend. Use a read-only operation to check the connection.
"That address is not reachable from a service"The address resolves to a private or local network. Services reach public APIs only.
"Services must use https"Plain http is never allowed.
"This service points at … which has a built-in service of its own"Use the built-in family; it carries protections a hand-described service would not.
A warning or error dot on the nodeA call failed. Open the service to see the last error.
"Services need a Pro plan"The schema owner is on the free plan, or their subscription lapsed.
A sender reports 401 from your addressThe signature did not match. Check they are using the secret you were shown, and signing the exact body they send.
A sender reports 402The schema is disconnected — the owner's subscription has lapsed.
A sender reports 429More than 600 in an hour reached that address.