Skip to content

Developers

Connect an AI system

Register an agent, application, model or automation with OpsAI, describe what it can reach, and start sending the events that make it observable.

Two shapes

Ask
Your code evaluates and honours the answer. Governs the call sites you instrumented.
Route
The action goes through OpsAI. Cannot be bypassed by forgetting.

Pick one deliberately

Asking is a starting point. Routing is the control.

These are not two flavours of the same integration. One depends on your code choosing to ask, and one does not — and the difference decides whether governance survives the next person who adds a code path.

Ask — evaluate, then act

Ten minutes to adopt and it works with anything. The limitation is structural rather than technical: an action taken from a path nobody instrumented is ungoverned, and nothing about the system will tell you that path exists.

Ask
const decision = await opsai.actions.evaluate({
  agent: 'refund-resolver',
  action: 'issue.refund',
  subject: 'ORD-40122',
});

if (decision.outcome !== 'authorized') return;

// Your code still performs the action.
await razorpay.refunds.create(, decision.grant);

Route — let OpsAI carry it out

The credential lives with OpsAI, so the action is evaluated on the way through. There is no unguarded path, because the only path to the system requires the decision to have happened.

Route
// No Razorpay credential in your process at all.
const result = await opsai.actions.perform({
  agent: 'refund-resolver',
  action: 'issue.refund',
  subject: 'ORD-40122',
  amount: { currency: 'INR', value: 18400 },
});

result.decision;  // 'authorized'
result.performed; // true
result.evidence;  // 'EV-7512'

What OpsAI needs to know

Register what exists, not what you are about to build.

Four fields matter and two of them are commonly misunderstood. Registration describes an AI system that is already running — it does not create, deploy or configure anything.

Register an AI system
const agent = await opsai.agents.create({
  // Stable identifier. Appears in every trace and every evidence record.
  id: 'refund-resolver',

  // REQUIRED. One accountable human — not a team, not a rota.
  owner: 'priya@acme.internal',

  // Descriptive only. Nothing in OpsAI branches on this.
  framework: 'langgraph',
  model: 'claude-sonnet',

  // The actions this system may ATTEMPT. A policy still decides each one.
  attempts: ['issue.refund', 'lookup.order'],

  // Optional. Where this system sits on the autonomy ladder.
  autonomy: 'acts_within_bounds',
});
owner is required
And cannot be a team. Every question asked after an incident is a question about a person, and a record that cannot name one cannot answer any of them.
framework changes nothing
It is recorded because the spread across an estate is worth knowing, not because behaviour varies by it. The 8 frameworks in the sample estate are governed identically.
attempts is a ceiling, not a grant
Listing an action means the system may propose it. A policy still decides every individual case, and the connection is a second ceiling above both.
autonomy can move down on its own
Breaking a bound drops the system a rung automatically. Coming back up is a decision a person makes, and only once a rule exists that would have caught it.

The system side

A connection holds the credential and declares what it permits.

The permitted-action list is a ceiling rather than a channel: an action absent from it cannot be authorized by any policy, which makes a connection the cheapest way to bound a whole class of mistake.

Connections in the sample estate

12 systems · 11 connected
Every system in the sample estate: what kind it is, whether it is connected, and the actions the connection permits.
SystemCategoryStatusActions it permits
RazorpayPaymentsConnectedissue.refund · capture.payment
RazorpayXPayoutsConnectedinitiate.payout
Zoho BooksAccountingConnectedpost.journal_entry
NetSuiteERPConnectedcreate.vendor · update.vendor
SalesforceCRMConnectedupdate.record
PostgresDatabaseConnectedadjust.stock · update.row
ZendeskSupportConnectedclose.ticket
GmailEmailConnectedsend.email
SlackMessagingConnectednotify · request_cosign
Amazon S3StorageConnectedexport.dataset
BoxDocumentsConnectedread.contract
WorkdayHRNot connected

Systems

12

in the register

Connected

11

credential held by OpsAI

Not connected

1

listed, not hidden

Credentials your code holds

0

grants are derived per action

IllustrativeThe OpsAI sample estate. Workday is unconnected, and stays in the register because an inventory that only lists what works is not an inventory.

Create a connection
const connection = await opsai.connections.create({
  system: 'Razorpay',

  // Supplied once. No endpoint returns this value afterwards, at any scope.
  credential: { kind: 'api_key', value: process.env.RAZORPAY_KEY },

  // The ceiling. Nothing outside this list can be authorized.
  allows: ['issue.refund', 'payment.read'],
});

// Reading it back never includes the secret.
const read = await opsai.connections.get(connection.id);
read.credential; // { kind: 'api_key', held: true, value: undefined }

Where to go

Wire the events next, then tighten the policy.

Once actions route through a connection, the things worth knowing about are the ones your own systems cannot see: a hold waiting on somebody, and a hold that expired because nobody looked.