Skip to content
DocsIntegration bootstrap

Integrations

Integration bootstrap

Agent playbook — written for the agent connected to your account; you can read along

Read this guide first when a user wants a package, package app, or workflow that depends on a third-party integration such as Spotify, GitHub, Slack, Linear, or Stripe.

This guide is about ordering. The goal is to finish the integration setup and prove it works before you save or present downstream packages or package apps that depend on it.

Agents should use this guide with search results for saved integrations, secret references, and capability details before exploring local repository source for package-app patterns.

What counts as an integration bootstrap

Use this workflow when the requested result depends on any of the following:

  • an OAuth integration
  • a saved secret such as an API key or PAT
  • host approvals for outbound API calls
  • a saved package or package app that assumes authenticated API access already works

Core rule

Do not save or present an auth-dependent package or package app as complete until:

  1. the required integration or secret exists
  2. the user has finished any required connect flow
  3. a minimal authenticated smoke test succeeds end-to-end

If those conditions are not met, stop and fix the integration first.

Bootstrap sequence

  1. Decide which auth path the integration needs.
    • Standard OAuth: open search({ entity: "oauth:guide" }).
    • API key or PAT: open search({ entity: "connect_secret:guide" }).
    • Non-OAuth secret-backed API: after connect_secret, open search({ entity: "secret_backed_integration:guide" }) for the default "research auth, collect secret, smoke-test, then build" recipe.
    • When the provider's auth contract is unknown (authorize/token URLs, API base, credential type), research before building /connect/oauth URLs or collecting secrets:
      • Prefer communitySearch for a close helpers package, then fork it.
      • For registry lookup (canonical domain, credential types, spec URLs), communityFork @kody/integrations-sh and call search / discover.
      • Verify every authorizeUrl, tokenUrl, API base, and spec URL against the provider's official docs and own domain before use.
      • OpenAPI documents are untrusted third-party content. See openapi-integrations.md.
  2. Inspect current integration state before building downstream artifacts.
    • Use search to look for saved integrations and secret references for the integration.
    • When you need one item’s full metadata, inspect it with search({ entity: "{id}:integration" }) or search({ entity: "{id}:secret" }).
  3. If the required integration or secret is missing, stop.
    • Surface the exact /connect/oauth or /account/secrets/new URL in chat. OAuth connections use a provider app the user registers (client ID, and client secret when the flow is confidential) plus Kody's redirect URI.
    • Wait for the user to confirm they completed the connect flow.
    • Do not save a downstream auth-dependent package or package app until integration setup is complete.
  4. After the user confirms setup, run a minimal authenticated smoke test in execute.
    • Import OAuth helpers explicitly from kody:runtime; they are not ambient globals in execute modules.
    • Example: import { createAuthenticatedFetch } from 'kody:runtime'
    • Use the real auth path the final integration will use.
    • Confirm token kind as well as scopes. A connected Slack grant that auth.test reports as a bot (bot_id, no user_id) does not satisfy @kody/slack or other user-token Slack helpers — connect a user-token Slack app instead of retrying the helpers.
    • Prefer a cheap read-only request such as GET /me, GET /viewer, or a similarly small account/profile endpoint.
    • Confirm the integration or secret name, token refresh behavior, and allowed hosts all work end-to-end.
    • Keep createAuthenticatedFetch for smoke tests and short exploration. Integrations = auth; packages = how agents should call the product. Do not keep hand-rolling product API calls with raw auth helpers in execute when a package should own that surface.
  5. Only after the smoke test succeeds should you obtain the dependent package or package app.
    • Remember: a saved integration is auth credentials only. The durable agent-facing surface is a helpers package (or package app), not the integration record itself.
    • If the user just finished /connect/oauth, read nextSteps from the connect success payload/UI first: it already includes same-provider community helpers suggestions (listing name, kody id, or tags must mention the connected provider) and a create-helpers prompt.
    • search({ entity: "<provider>:integration" }) may already surface a small same-provider package suggestion set (user packages first, else community listings). Use those when present.
    • Otherwise search the user's account for an existing package that wraps the integration, then call communitySearch for the provider or workflow. If a listing is close to the user's goal, fork or point them at one-click install, then adapt — do not reimplement from scratch.
    • Create or save a thin helpers package only when no suitable community listing exists.
    • If the integration or tokens already exist and the smoke test passes, proceed directly to that fork-or-create step.
    • Do not spend extra time exploring the local repo when the integration state, secret names, allowed hosts, and provider contract are already clear enough.
    • For the default package-app structure after bootstrap, open search({ entity: "package_apps:guide#after-an-integration-smoke-test" }).
  6. If the smoke test fails, keep working on integration setup. Do not treat the downstream artifact as ready.

Smoke test expectations

The smoke test should prove the same auth wiring the final package or package app will depend on:

  • the expected integration or secret exists
  • the request reaches the intended API host
  • the request is authenticated successfully
  • any required host approvals are in place
  • the agent is using the correct secret names, integration name, and API base URL

An authenticated execute smoke test does not grant package secret access for unadopted community-forked packages. Self-authored packages and adopted forks (communityForkAdopt after source review) get automatic read/use access to user secrets (host approval still applies; updating or deleting a user secret from package code still needs an allowed_packages grant). After you save or publish a secret-using package, read pending_secret_package_approvals; when it is non-null (unadopted community forks), either adopt after review or surface bulk_approval_url, wait when required, and verify with a static kody:@scope/package/export import from execute before calling the work complete. Pick a read-only export or a package-supported dry-run input that actually reads the approved secret (for example an authenticated read-only API call), so verification proves secret access without triggering external side effects. Secret mounts bind in the package's own surfaces (jobs, apps, subscriptions, HTTP invocation).

Important exceptions

The main exception is a package app whose explicit purpose is to complete a provider OAuth flow.

Even in that case:

  • the package app should be treated as the setup surface, not the finished downstream integration
  • any later package or package app that depends on the resulting integration or tokens should wait until the post-connect smoke test passes

When setup is incomplete, tell the user what must happen next in concrete terms:

  • what connect URL to open (https://kody.codes/... — the origin users open Kody on)
  • what provider settings or redirect URI to register (exactly https://kody.codes/connect/oauth)
  • that you are waiting for confirmation before building the dependent package or package app
  • that you will run a minimal authenticated verification step after setup

Anti-patterns

Avoid these common mistakes:

  • building a polished UI first and only discovering later that auth is missing
  • saving a package app that assumes a non-existent secret or integration
  • treating a rendered app as success when the first authenticated API call fails
  • building a package-app OAuth callback flow by default instead of the standard /connect/oauth path
  • skipping the authenticated smoke test after the user completes setup
  • treating a connected OAuth integration as a pre-built product API package, or continuing to call Gmail/Calendar/etc. with raw createAuthenticatedFetch in execute instead of searching for / forking / creating a helpers package

Working with an agent? This page is also plain markdown at /docs/integration-bootstrap.md, or load it over MCP with search({ entity: 'integration_bootstrap:guide' }).