17Docs

AI & managed services

Bounded adds real AI and third-party integrations inside server-side Functions. ctx.ai routes chat, image, and video generation without provider keys in app code; ctx.services lets an agent search, describe, and invoke managed API tools. Managed paid routes are beta: they bill the app owner and require stable replay keys, but availability and accounting recovery remain model-, tool-, and route-specific.

Choose the right surface

NeedUseResult
Chat, structured generation, classification, or reasoningctx.ai.runA provider-shaped model response, routed and metered by Bounded
Generate an imagectx.ai.generateImageA synchronous result, optionally saved to a governed storage collection
Generate a videoctx.ai.generateVideoAn asynchronous job; inspect it with ctx.ai.getJob or subscribe to a declared job mirror
Find and call a supported third-party APIctx.services.search, describe, and invokeCatalog discovery plus a managed, metered provider call
Own the upstream account and credentialsfetch plus ctx.secretsA direct provider integration that you operate and pay for

ctx.ai: chat, images, and video

ctx.ai.run(model, input, { idempotencyKey }) is the general model-inference API. The model id is configuration; the input uses that provider’s request shape. The required operation key must identify one business operation, not one network attempt.

Function, model inference then a governed write
export default async function answer(args, ctx) {
  const result = await ctx.ai.run(
    "claude-opus-4-8",
    {
      messages: [
        { role: "system", content: "Answer from the supplied project context." },
        { role: "user", content: args.question },
      ],
    },
    { idempotencyKey: `support:${args.threadId}:answer:${args.revision}` },
  );

  await ctx.bounded.set(`threads/${args.threadId}/answers/${args.revision}`, {
    text: result.response ?? result.choices?.[0]?.message?.content,
  });
  return { ok: true };
}

Image and video generation use their dedicated media APIs, not ctx.ai.run. Images can be returned or written to a policy-declared file collection. Videos return a job because generation takes longer; a declared aiJobs/$jobId document can mirror progress for an ordinary realtime subscription.

Function, native image and video generation
export default async function generateMedia(args, ctx) {
  // Image generation is synchronous and can write into a governed file collection.
  const image = await ctx.ai.generateImage({
    prompt: args.prompt,
    destinationPath: "generatedImages",
    metadata: { owner: ctx.user.id },
  });

  // Video generation is asynchronous. Subscribe to the optional job mirror,
  // or inspect the job later with ctx.ai.getJob(jobId).
  const video = await ctx.ai.generateVideo({
    model: "replicate/wan-video/wan-2.7-t2v",
    prompt: args.prompt,
    durationSeconds: 8,
    destinationPath: "generatedVideos",
    jobPath: "aiJobs",
  });

  return { imagePath: image.filePath, videoJobId: video.jobId };
}

ctx.services: discover, inspect, invoke

search finds relevant tools, describe returns their schemas, and invoke performs the managed provider call. Discovery is useful while an agent is building or planning; invocation is the runtime, cost-bearing step.

Function, managed service discovery and invocation
export default async function refreshOdds(args, ctx) {
  const matches = await ctx.services.search("sports odds", { limit: 5 });
  const schema = await ctx.services.describe("the_odds_api");

  const response = await ctx.services.invoke(
    "THE_ODDS_API_GET_ODDS",
    { sport: args.sport, regions: "us", markets: "h2h" },
    { idempotencyKey: `odds:${args.snapshotId}:v1` },
  );

  await ctx.bounded.set(`oddsSnapshots/${args.snapshotId}`, {
    result: response.result,
  });
  return { matches, schema };
}
  • ctx.services.invoke requires an app-global operation key. Reusing the same key with the same tool, entity, account, and exact arguments replays the saved result. Reusing it for changed work is a conflict, not a second provider call.
  • Catalog reads do not invoke a provider. A managed invocation bills the app owner’s AI/external-services bucket at the applicable upstream service cost plus 5%.
  • If a managed provider is not enabled, discovery may still succeed while invocation fails with a specific configuration error. Do not treat catalog presence as proof that a provider call will run.

Idempotency and the paid-route release gate

Use one app-global key per business operation and never rotate it after an ambiguous result. The runtime can deny unsupported pricing, missing replay provenance, or insufficient account credit before some managed calls, but reservation, settlement, refund, and provider-outcome recovery remain route-specific beta behavior.

  • Operation keys are app-global. Include the callsite, entity, and a revision, such as prospect:42:assessment:v2.
  • A direct browser or server invocation of a Function that performs paid AI/service work also needs a stable outer HTTP Idempotency-Key. Scheduled and system invocations already carry stable replay provenance.
  • For cost-sensitive production workflows, use a direct provider integration with provider-side idempotency and reconciliation until the exact managed route has published live fault/recovery evidence. Never rotate an operation key to bypass an outcome-unknown state.

Direct provider integration (BYOK)

The managed path is optional for third-party services. A Function can call a provider directly with fetch and retrieve your key from ctx.secrets. You then pay the provider directly, and Bounded’s managed-service 5% markup does not apply.

A direct integration also leaves the managed catalog, billing, and replay contract. Keep keys out of client code, use the provider’s idempotency controls, and reconcile ambiguous results yourself. For model and media inference, ctx.ai remains the keyless, Bounded-managed route.

What is proved, enforced, and not proved

StatusWhat it covers
ProvedOnly the supported policy obligations that bounded verify reports as proved, including declared state invariants on the writes modeled by that obligation
Runtime-enforcedFunction invocation auth, collection rules, and applicable invariants when AI/service results are written through ctx.bounded
Not provedThe Function body, prompt quality, model output, third-party correctness or availability, and whether generated content is factually true

Keep state guarantees in policy, not in a prompt or Function body. Read Functions for the imperative boundary and Files & search for governed generated assets.