DocsAI agents
The worker
The process that runs agent payments. It saves each payment before it signs, and never sends twice.
The worker is the process that runs agents. It is hosted on Railway, one service per network: one for testnet and one for mainnet, each with its own database. It reads each registered agent's rule, turns due payments into payment intents, sends them from the agent's own wallet, and reconciles every payment from the chain.
#The loop
- It checks every 30 seconds. When nothing is happening it waits longer, up to 15 minutes.
- When an owner changes an agent (creates it, changes its mode, its rule or its state, records a reading or confirms a payment), the app wakes the worker so the change applies at once.
- It never waits past a scheduled payment's due time.
#How one payment is made
- The intent is saved first. When a rule comes due, the worker writes a payment intent to its database, with its own reference, before anything can sign. In Observe mode the intent is only recorded. In Confirm mode it waits for the owner.
- The binding is checked. The right chain and account, the agent still active, the mode still allowing it, the intent not expired, and the signing wallet being the agent's own.
- The chain is read fresh. The account's pause, the agent's policy, the service, whether the reference was already used, and the latest block. If any read fails, the worker waits and tries again. It never sends on a read it did not get.
- The exact payment is simulated from the agent's wallet. If the contract would refuse it, the intent is recorded as refused by the policy and nothing is sent.
- The commit point. The worker records that it is about to send, then sends through the agent's Privy server wallet, with the gas sponsored when that is on. The transaction hash is saved the moment it exists.
- It reconciles. The payment is read back from its receipt, and counted as final only once its block is final.
#Why it never pays twice
- Each intent has its own reference, and the contract records each reference once per spender. A second payment with the same reference is refused on chain.
- The worker's database refuses a second attempt while an earlier one might still land.
- If a send times out or its outcome is unclear, the intent becomes pending, never failed, and is never sent again. The reconciler finds out what happened from the chain.
- If the contract already shows the reference as used, the worker looks for that payment's receipt and records it. It does not send.
#When something goes wrong
| What happened | What the worker does | Money moved? |
|---|---|---|
| The contract would refuse the payment | Records it as refused by the policy | No |
| A chain read failed | Tries again later, with growing waits | No |
| Privy rejected the send before broadcasting | May try again; otherwise needs a person | No |
| The send timed out or the result is unclear | Marks it pending and reconciles from the chain | Not yet known |
| Retries ran out, or something did not add up | Marks it as needing a person | No, unless a send is still pending |
#Modes and the worker's ceiling
The worker has its own ceiling, set on the service. Each agent runs at the lower of its own mode and that ceiling. A worker set to Observe sends nothing for any agent.
#What the worker refuses at startup
- A network other than testnet or mainnet, or settings that disagree about which one.
- An RPC endpoint that answers for another chain.
- An account that is not VERSION 2 and sealed on chain.
- An owner key loaded while it is allowed to sign.
- On mainnet, a raw private key as an agent's signer, unless explicitly allowed.
There is also a kill switch: with it on, the worker stops before it touches anything.
#Seeing its state
Each agent's page shows the worker's latest check-in: whether it is running, when it last checked in, its ceiling, and whether it pays agents' gas. If the worker's state cannot be read, the page says it is unknown, which is not the same as stopped. The public health check at /api/health reports the same, for example nuntio.finance/api/health.