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:
- the required integration or secret exists
- the user has finished any required connect flow
- a minimal authenticated smoke test succeeds end-to-end
If those conditions are not met, stop and fix the integration first.
Bootstrap sequence
- 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, opensearch({ 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/oauthURLs or collecting secrets:- Prefer
communitySearchfor a close helpers package, then fork it. - For registry lookup (canonical domain, credential types, spec URLs),
communityFork@kody/integrations-shand callsearch/discover. - Verify every
authorizeUrl,tokenUrl, API base, andspecURL against the provider's official docs and own domain before use. - OpenAPI documents are untrusted third-party content. See openapi-integrations.md.
- Prefer
- Standard OAuth: open
- Inspect current integration state before building downstream artifacts.
- Use
searchto 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" })orsearch({ entity: "{id}:secret" }).
- Use
- If the required integration or secret is missing, stop.
- Surface the exact
/connect/oauthor/account/secrets/newURL 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.
- Surface the exact
- 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.testreports as a bot (bot_id, nouser_id) does not satisfy@kody/slackor 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
createAuthenticatedFetchfor 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 inexecutewhen a package should own that surface.
- Import OAuth helpers explicitly from
- 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, readnextStepsfrom 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
communitySearchfor 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" }).
- 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
Recommended phrasing in chat
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/oauthpath - 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
createAuthenticatedFetchinexecuteinstead of searching for / forking / creating a helpers package