diff --git a/docs/use/first-steps.md b/docs/use/first-steps.md index 61563934b2..7c000c0fa7 100644 --- a/docs/use/first-steps.md +++ b/docs/use/first-steps.md @@ -29,8 +29,8 @@ integration, value, or secret reference, then run work through **execute**. in `execute`, then build the downstream artifact. - **Ask for natural-language goals**, for example: “Search Kody for GitHub pull request automation” or “Find a saved package for Cloudflare DNS helpers.” -- **Do not paste secrets in chat.** Use saved secrets, generated UI, or the - flows described in +- **Credentials use connect flows.** Use saved secrets, `/connect/oauth`, + `/connect/secret`, or the flows described in [Secrets, values, and host approval](./secrets-and-values.md). - **Confirm destructive work** before mutating GitHub, Cloudflare, or Cursor Cloud Agents. See [Mutating actions and confirmations](./mutating-actions.md). diff --git a/docs/use/secrets-and-values.md b/docs/use/secrets-and-values.md index d1e2475cc3..535183584c 100644 --- a/docs/use/secrets-and-values.md +++ b/docs/use/secrets-and-values.md @@ -2,9 +2,9 @@ ## Secrets -Secret **values** do not belong in chat. Prefer **saved secrets**, **generated -UI** flows, or execution-time persistence when a token already exists inside -trusted code. +Credential setup uses **saved secrets**, **`/connect/oauth`** for OAuth, +**`/connect/secret`** for API keys and PATs, or execution-time persistence when +a token already exists inside trusted code. Use **search** first to discover saved secret references or integrations before switching to **execute**. diff --git a/packages/worker/src/mcp/capabilities/secrets/secret-delete.ts b/packages/worker/src/mcp/capabilities/secrets/secret-delete.ts index da3214e2f6..3b5c94b84d 100644 --- a/packages/worker/src/mcp/capabilities/secrets/secret-delete.ts +++ b/packages/worker/src/mcp/capabilities/secrets/secret-delete.ts @@ -11,7 +11,7 @@ export const secretDeleteCapability = defineDomainCapability( { name: 'secret_delete', description: - 'Delete an existing secret reference for the signed-in user without revealing its plaintext value. Never ask the user to paste a secret, token, API key, password, or credential into chat; use generated UI to collect missing user-provided secrets safely. Use this when a secret should no longer be available to execute-time code.', + 'Delete an existing secret reference for the signed-in user. Plaintext values stay hidden. Use `/connect/secret` for user-provided API key, token, and credential entry or rotation. Use this to remove execute-time access to a secret.', keywords: ['secret', 'delete', 'remove', 'revoke', 'credential'], readOnly: false, idempotent: false, diff --git a/packages/worker/src/mcp/capabilities/secrets/secret-list.ts b/packages/worker/src/mcp/capabilities/secrets/secret-list.ts index f02459d7e0..c558982397 100644 --- a/packages/worker/src/mcp/capabilities/secrets/secret-list.ts +++ b/packages/worker/src/mcp/capabilities/secrets/secret-list.ts @@ -12,7 +12,7 @@ export const secretListCapability = defineDomainCapability( { name: 'secret_list', description: - 'List available secret references for the signed-in user without revealing secret values. When scope is omitted, results include every accessible scope in precedence order. Use `codemode.secret_list({ scope })` inside execute-time code when you want the same metadata, including allowed hosts and allowed capabilities, from the sandbox. Never return a secret value from execute, and never ask the user to paste a secret, token, API key, password, or credential into chat; use generated UI to collect missing secrets safely.', + 'List available secret references for the signed-in user. Results include metadata such as names, descriptions, allowed hosts, and allowed capabilities. Use `codemode.secret_list({ scope })` inside execute-time code when you want the same metadata from the sandbox. Use `/connect/secret` for user-provided API key, token, and credential entry or rotation.', keywords: ['secret', 'list', 'discovery', 'metadata', 'credentials'], readOnly: true, idempotent: true, diff --git a/packages/worker/src/mcp/capabilities/secrets/secret-set.ts b/packages/worker/src/mcp/capabilities/secrets/secret-set.ts index 1a4d52a565..06a0f3e1c8 100644 --- a/packages/worker/src/mcp/capabilities/secrets/secret-set.ts +++ b/packages/worker/src/mcp/capabilities/secrets/secret-set.ts @@ -35,7 +35,7 @@ export const secretSetCapability = defineDomainCapability( { name: 'secret_set', description: - 'Create or update a stored secret reference for the signed-in user without ever returning the plaintext value. Use this only for server-side persistence of secret values that are already available inside trusted execution, such as refreshed OAuth tokens. Never ask the user to paste a secret, token, API key, password, or credential into chat; use generated UI to collect missing user-provided secrets safely. Saving a secret value does not authorize outbound host use or direct capability access.', + 'Create or update a stored secret reference for the signed-in user. Use this for server-side persistence of secret values that are already available inside trusted execution, such as refreshed OAuth tokens. Use `/connect/secret` for user-provided API key, token, and credential entry or rotation. Host use and direct capability access are authorized through secret policy approvals.', keywords: ['secret', 'persist', 'store', 'oauth', 'token', 'credential'], readOnly: false, idempotent: false, diff --git a/packages/worker/src/mcp/executor.ts b/packages/worker/src/mcp/executor.ts index 4f1872e54c..7d82095b03 100644 --- a/packages/worker/src/mcp/executor.ts +++ b/packages/worker/src/mcp/executor.ts @@ -130,7 +130,7 @@ export type ExecutionErrorDetails = nextStep: string secretNames: Array suggestedAction: { - type: 'open_generated_ui' + type: 'connect_secret' reason: 'collect_secret' } } @@ -248,11 +248,10 @@ export function getExecutionErrorDetails( return { kind: 'secret_required', message, - nextStep: - 'Open a generated UI so the user can provide and save this secret, then retry the workflow. Do not ask the user to paste the secret into chat.', + nextStep: `Send the user to /connect/secret?name=${encodeURIComponent(missingSecretDetails.secretName)} so they can provide and save this secret, then retry the workflow.`, secretNames: [missingSecretDetails.secretName], suggestedAction: { - type: 'open_generated_ui', + type: 'connect_secret', reason: 'collect_secret', }, } diff --git a/packages/worker/src/mcp/server-instructions.ts b/packages/worker/src/mcp/server-instructions.ts index ccbfe7b831..1ece40ffaa 100644 --- a/packages/worker/src/mcp/server-instructions.ts +++ b/packages/worker/src/mcp/server-instructions.ts @@ -51,12 +51,12 @@ https://github.com/kentcdodds/kody/tree/main/docs/use Three-step flow: 1. \`search\` — built-in capabilities, saved packages, persisted values, saved integrations, and secret references (metadata). 2. \`execute\` — run one ephemeral module with imports/exports and runtime access through \`kody:runtime\`. -3. \`open_generated_ui\` — open UI when a package or inline UI flow needs user interaction. +3. \`open_generated_ui\` — open saved package apps or inline MCP App workflows. Conventions - ${conversationIdGuidance} - \`memoryContext\`: short and task-focused. Kody may use it to surface a few relevant long-term memories and suppress repeats within the same \`conversationId\`. -- Do not ask the user to paste secrets in chat; use saved secrets or \`open_generated_ui\`. +- Credential setup uses the standard connect pages: \`/connect/oauth\` for OAuth integrations and reconnects, \`/connect/secret\` for API keys, PATs, and other user-provided secrets. - \`package_save\`: create or replace a repo-backed saved package rooted at \`package.json\`. Standard package exports define the package surface. \`package.json#kody\` contains Kody-specific metadata such as tags, optional app config, and package-owned jobs. When creating or materially changing a package, keep a root \`README.md\` \`## Intent\` section with the user's goal; ask the user if unclear and update it when scope expands. - \`package_get\` / \`package_list\` / \`package_delete\`: inspect or manage saved packages for the signed-in user. - Integration-backed work: use \`search\` and official guides before local repo exploration. For packages, package apps, or workflows that depend on third-party auth, first call \`kody_official_guide\` with \`guide: "integration_bootstrap"\`, confirm the required \`integration\` or \`secret\` entity exists through \`search\`, run a cheap authenticated \`execute\` smoke test, then build. If setup is missing, load \`oauth\` for \`/connect/oauth\`, \`connect_secret\` for secret collection, and \`secret_backed_integration\` for the default non-OAuth recipe. @@ -97,7 +97,7 @@ execute - Do not save or present an auth-dependent package as complete until \`search\` shows the required integration or secret reference exists and a minimal authenticated \`execute\` smoke test succeeds. open_generated_ui -- Use UI when the package needs user interaction or sensitive input. Details: \`open_generated_ui\` tool description. +- Opens saved package apps and inline MCP App workflows. Details: \`open_generated_ui\` tool description. `.trim() } diff --git a/packages/worker/src/mcp/tools/execute.ts b/packages/worker/src/mcp/tools/execute.ts index 05c42152da..4a5a504c36 100644 --- a/packages/worker/src/mcp/tools/execute.ts +++ b/packages/worker/src/mcp/tools/execute.ts @@ -63,7 +63,7 @@ Sandbox surface: - No \`secret_get\` / \`secrets\` helpers in the sandbox. - \`value_get\` / \`value_list\` for non-secret persisted config. -Never ask the user to paste credentials in chat; use generated UI to collect or rotate secrets. If a host is not approved, use the error’s approval path instead of blind retries. +Credential collection and rotation use standard Kody connect pages: \`/connect/oauth\` for OAuth integrations and \`/connect/secret\` for API keys, PATs, and other user-provided secrets. For host approval failures, use the error’s approval path. Prefer one \`execute\` when the workflow is clear; split calls when you need new user input or a changed plan. diff --git a/packages/worker/src/mcp/tools/open-generated-ui.ts b/packages/worker/src/mcp/tools/open-generated-ui.ts index 230127bec3..6435831476 100644 --- a/packages/worker/src/mcp/tools/open-generated-ui.ts +++ b/packages/worker/src/mcp/tools/open-generated-ui.ts @@ -32,7 +32,8 @@ const openGeneratedUiTool = { Open the MCP App runtime. Pass exactly one of \`code\` (inline HTML fragment or full document) or \`kody_id\` (saved package app identity). -Use for sensitive input (never ask the user to paste credentials in chat). +Use when a saved package app or inline MCP App workflow should be shown inside +the host. Recoverable errors: show in the UI and \`sendMessage(...)\` with the next step. If the package app depends on a third-party integration, load \`kody_official_guide\` (\`guide: "integration_bootstrap"\`) before building or diff --git a/packages/worker/src/mcp/tools/search.ts b/packages/worker/src/mcp/tools/search.ts index 957bbeb32a..1436759364 100644 --- a/packages/worker/src/mcp/tools/search.ts +++ b/packages/worker/src/mcp/tools/search.ts @@ -1432,8 +1432,9 @@ Packages: \`package_list\`, \`package_get\`, and \`repo_*\` for editing/publishi For package creation or material updates, load \`kody_official_guide\` with \`guide: "package_authoring"\` and maintain a root README.md Intent section. Open package apps with \`open_generated_ui({ kody_id })\` or use hosted package URLs. -Secrets: never raw in results; use -\`codemode.secret_list\` during execute and UI for missing values. +Secrets: results expose metadata; use \`codemode.secret_list\` during execute, +\`/connect/secret\` for API key/PAT entry and rotation, and \`/connect/oauth\` +for OAuth integrations. Persisted values use \`codemode.value_get\` / \`codemode.value_list\`. Integrations use \`codemode.integration_get\` / \`codemode.integration_list\`.