Search

Search the documentation

Protobox
Use cases

Your API as agent tools

Register your own OpenAPI spec — or a code bundle — as a private connector, and your product's actions become first-class agent tools beside the catalog.

Scenario: Acme's assistant shouldn't only act on other products — the highest-value tools are Acme's own: create_ticket, escalate, issue_refund. Registering Acme's API as a private connector makes those actions identical citizens to Gmail or HubSpot: same execution pipeline, same policies, same traces, same MCP serving.

Private connectors are visible only to your workspace. Two shapes: an OpenAPI spec (your existing API, zero new code) or a code bundle (logic that isn't one HTTP call).

From an OpenAPI spec

const connector = await protobox.connectors.registerOpenApi({
  slug: 'acme',
  spec: 'https://api.acme.com/openapi.json',   // inline OpenAPI 3.x object also accepted
  name: 'Acme',
  // Don't tool-ify all 120 operations — pick the agent-safe ones:
  operations: { include: ['createTicket', 'searchTickets', 'escalateTicket'] },
  // Relay caller context (your conversation/user ids) as a header on each call:
  forwardContext: true,
});

Each included operation becomes an action named ACME_<OPERATION>; auth is auto-mapped from the spec's securitySchemes (override with auth if needed).

Authenticate calls to your API

Your API needs a credential too. For a service-level token (one credential for the whole workspace):

await protobox.authConfigs.create('acme', {
  mode: 'service',
  credentials: { token: process.env.ACME_INTERNAL_API_TOKEN!, headerName: 'X-Acme-Key' },
});

mode: 'service' is principal-level infrastructure auth — no per-user OAuth dance, the platform presents the token on every call. Per-user auth modes work here exactly as for catalog apps.

Keep it in sync

When your API changes, diff-sync instead of re-registering:

const diff = await protobox.connectors.syncOpenApi('acme', { spec: newSpec });
// Arrays carry the spec's operationIds, not the prefixed action names:
// { added: ['closeTicket'], removed: [], changed: ['createTicket'] }

Run it from CI on API releases and alert on removed/changed — those can break live agents.

From a code bundle

For tools that aren't one endpoint call — aggregate three internal services, transform data, enforce invariants.

Your entry point exports one async function, and it receives the tool's arguments object directly — not wrapped in an envelope:

// index.js — the entry point named by `entryPoint`
module.exports = async function run(args) {
  // args is exactly what the caller passed as `arguments`
  return { period: args.period, rows: 3 };
};

invokeTest and live agent execution hand the module the same object, so what you smoke-test is what runs in production.

const result = await protobox.connectors.registerCode({
  slug: 'acme-reports',
  name: 'Acme reports',
  runtime: 'node',                         // or 'python'
  entryPoint: 'index.js',
  files: [
    { path: 'index.js', content: reportToolSource },
  ],
  requiredSecrets: ['ACME_DB_URL'],        // resolved per-workspace at run time
});

Bundles run in a managed sandbox. Secrets named in requiredSecrets are injected from the workspace vault — set them once:

await protobox.secrets.set({
  principalId: 'acme',   // shape-required; the workspace itself is resolved from your API key
  key: 'ACME_DB_URL',
  value: process.env.ACME_DB_URL!,
});

Secrets can also be actor-scoped (actorId: 'user_123') so each end-user's run resolves their own value — the same two-level model as connections.

Test before agents touch it

const test = await protobox.connectors.invokeTest('acme-reports', {
  arguments: { period: 'last_7_days' },
});
console.log(test.success, test.latencyMs, test.logs);

invokeTest is a management-API harness — full sandbox logs, timing, and exit code, not a billed execution.

Use it everywhere

The moment it's registered, your connector is just another connector:

// In an agent conversation:
const acme = user.forLLM('anthropic', { integrationId: 'acme' });

// In a curated toolset (mixed with catalog tools), served over MCP:
const toolset = await protobox.toolsets.create({
  name: 'Support agent',
  tools: [/* acme tool ids + gmail tool ids */],
});

// From a background job:
await protobox.actions.execute('ACME_CREATETICKET', {
  actorId: 'user_123',
  arguments: { subject: 'Renewal follow-up', priority: 'high' },
});

Retire it cleanly with protobox.connectors.setRegistrationStatus('acme', 'disabled') (reversible) or protobox.connectors.unregister('acme') (gone).

On the roadmap: registering an external MCP server you already run as a private connector — same curation, policies, and serving over its tools. Today's private connectors are OpenAPI and code bundles.

Production notes

  • Curate with operations.include. An agent with your full admin API is an incident waiting to happen. Start with 3–5 read-mostly operations; add writes behind approvals.
  • forwardContext: true relays execution context verbatim as an X-Protobox-Context header — your API can log or scope by your own conversation/user ids without Protobox ever parsing them.
  • Bundle limits: ≤20 files, ≤200KB each, ≤1MB total, one entry point.

On this page