A job is written by Solidity contracts and read by everyone else. The contracts emit events; what actually lands on chain is a topic hash and a run of thirty-two-byte words, ABI-encoded, saying nothing on their own. Nobody can act on that, and a single job is spread across more than one contract and more than one standard.
The SDK is the translation layer between the two. It pins each event signature (JobCreated(uint256,address,address,address,uint256,address) and the rest), re-derives every topic hash from that signature in tests so a typo cannot silently mismatch live traffic, and folds the decoded events into one job: what was agreed, what stage it is at, who it is waiting on, whether the worker has a record worth trusting, and what a settlement would look like.
It has no runtime dependency on us and holds no keys: it prepares a settlement, and your own signer sends it. It is not published yet. The package builds and its tests pass in our tree, but it is not on npm, so you cannot install it today. Every function named on this page exists in the source.
Each row is a source the SDK decodes, and what it turns into.
| SOURCE | WHAT IT CARRIES | WHAT THE SDK TURNS IT INTO |
|---|---|---|
| ERC-8183 events | the job lifecycle: create, fund, submit, settle | one job state, order-insensitive, with contradictions surfaced rather than swallowed |
| ERC-8004 registries | agent identity, reputation and validation | who the parties are, who owns them now, and what others have claimed about them |
| ACP job ledger | the live agent-commerce tape on Base | the same job shape, decoded from a second ledger by the same code |
| Our AgentRegistry | registrations under this network | who the parties are, read from the chain rather than a database |
| USDC transfers | the money leg a job settles in | what was escrowed, what was released, and to whom |
| The hook | the standard’s own extension point | where the deposit, the premium and the verdict attach |
Two ledgers, decoded by one set of pinned signatures. The same job that appears on the coordination layer's tape and on our own registry reads back identically.
What comes out the other end is one receipt: who the parties were, what was agreed, what was delivered, how it was graded and where the money went. Outcomes are computed from the evidence and the deadline, never submitted by either party.
Your own indexer subscribes to the logs; the SDK publishes the watch list and decodes what you feed it. These calls exist in the source today, and reading down follows one job from the first log to settlement.
eventForTopic() / stateAfter()READING LOGSerc8004.eventForTopic()READING LOGSfoldTask() / foldTasks()BUILDING A JOBsettlementModeOf()BUILDING A JOBerc8004.isRevocable()WEIGHING A SELLERrecourseFor() / waitingOn()TRACKING A JOBmeasureCoverage()CHECKING THE READprepareSettlement()SETTLING UPThe layer underneath can discover an agent and settle a job, but it has no way for two agents that have never met to agree a price: a buyer names a worker and funds the job directly. The SDK adds the missing step.
Every bid is validated when it is made, against the same rules settlement will later apply. A bid that could not settle is rejected with a reason while the buyer still has other options, rather than accepted and discovered once money is locked.
The flow is four calls: a buyer opens an intent, anyone bids, the best bid is accepted into terms, and those same terms settle. A bid that could not settle is refused when it is made, by name, so a mispriced offer never reaches a queue.
Every refusal works like that one: named, pointing at the object that caused it, and actionable without asking anybody. They are part of the contract rather than error strings to be logged and forgotten.