← KoraCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Kora
Snapshot Sep 30, 2026 · 23:13 UTC · version 0.12.1
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"description": "Read when evaluating whether a target Kora deployment supports custom extension packages, creating or changing package source for self-managed Kora, validating or publishing that source, or routing a hosted Kora user to Kora-shipped built-in extensions.",
"included_files": [
{
"relative_path": "agents/openai.yaml",
"size_in_bytes": 329
},
{
"relative_path": "assets/kora-mark.png",
"size_in_bytes": 24826
},
{
"relative_path": "references/extension-context.md",
"size_in_bytes": 5817
},
{
"relative_path": "references/functions-and-tools.md",
"size_in_bytes": 7208
},
{
"relative_path": "references/manifest-and-entrypoint.md",
"size_in_bytes": 5710
},
{
"relative_path": "references/settings-callbacks-schedules.md",
"size_in_bytes": 7912
}
],
"name": "kora-extension-builder",
"skill_md_contents": "---\nname: kora-extension-builder\ndescription: \"Read when evaluating whether a target Kora deployment supports custom extension packages, creating or changing package source for self-managed Kora, validating or publishing that source, or routing a hosted Kora user to Kora-shipped built-in extensions.\"\n---\n\n# Kora Extension Builder\n\nUse this skill when the user wants to create or change extension package source.\nExtension packages are separate source bundles with their own lifecycle; they\nare not workflow release-source files.\n\n## Resolve The Target First\n\nDetermine the deployment mode before creating files or running package\ncommands. In Kora Chat, use the deployment mode stated in the operating\ncontext. In an external agent, use an explicit user statement or ask whether\nthe target is Kora SaaS or self-managed Kora. Do not infer deployment mode from\na hostname.\n\n- **Hosted Kora SaaS:** customer extension-package validation, publication,\n and direct installation are unavailable. Do not create a package that you\n imply can be validated or installed there, and do not run `extensions\n validate` merely to rediscover the restriction. Search installed or\n available Kora-shipped built-ins and route installation/setup to the\n Extensions Settings surface from `kora-product-ui`.\n- **Self-managed Kora:** custom packages may be authored. The deployment still\n owns authorization and lifecycle checks; follow the build flow below.\n- **Source explicitly intended for a separate self-managed deployment:** you\n may author it while the current chat is hosted, but state that it cannot be\n validated, published, or installed against the hosted organization. Stop\n after source-only checks unless the user supplies an eligible self-managed\n target.\n\nWhen the extension targets a named third-party product, vendor, API, or public\nservice, research first. In Kora chat, use `web_search` and then `web_fetch` on\nthe most relevant official docs or product pages before choosing endpoints,\nauth style, request fields, or response fields. Do not design provider-specific\nbehavior from model memory alone. If web research is unavailable, fails, or does\nnot find useful official sources, say that plainly and either ask for a docs URL\nor continue only with clearly labeled assumptions and a generic adapter shape.\n\nFor an eligible self-managed target, an authoring agent can create and edit\nextension package source in the workspace, validate it with `kora extensions\nvalidate <path> --json`, and publish it with `kora extensions publish <path>\n--json` when the user asks to publish.\nInstall, permission grants, removal, built-in installation, secrets,\nOAuth/callback setup, and extension settings UI are deployment operations, not\nextension package source authoring.\n\n## Mental Model\n\nAn extension package workspace contains:\n\n```text\nextension.yaml\nsrc/**\nskills/**\nassets/**\nREADME.md\n```\n\n`extensions publish` stores an immutable published package. Extension install,\ngrant, enable/disable, configuration, and removal are environment-scoped\nSettings actions.\n\nThe manifest declares requested permission limits. Grants are install-owned\napproval; do not hard-code approval into package source.\n\n## Build Flow\n\nAfter resolving an eligible self-managed target, follow this order:\n\n1. Decide what the extension is for: static callable functions, static agent\n tools, dynamic agent tools, install settings, public callbacks, schedules,\n bundled runtime skills, hooks, or a combination of those surfaces. For named\n third-party systems, do the official-source web research above before\n drafting package source.\n2. Create a package directory in the workspace, normally under\n `extensions/<package-name>/`.\n3. Write `extension.yaml` with package metadata, metadata-only version,\n entrypoint, requested permissions, and timeout limits.\n4. Write `src/index.ts` with a default registration function that imports\n `Type` from `@kora/extension-sdk` and registers the needed surfaces.\n5. Add package-local skill files under `skills/<skill-name>/SKILL.md` only when\n the installed extension should provide bundled runtime skills.\n6. Add package assets under `assets/**` when handlers or bundled skills need\n immutable package-local files.\n7. Run `kora extensions validate extensions/<package-name> --json`.\n8. Fix validation diagnostics until validation returns `ok: true`.\n9. When the user wants an installable package, run\n `kora extensions publish extensions/<package-name> --json`.\n10. Tell the user the package is published but not installed yet, then provide\n the Settings route from `kora-product-ui` for installation and setup.\n\nDo not skip from invalid source to install. `extensions publish` runs package\nvalidation again and only stores an immutable published package if the package\nis valid.\n\n## Authoring Commands\n\nUse these package lifecycle commands while building package source:\n\n- `kora extensions validate <package-dir> --json`\n- `kora extensions publish <package-dir> --json`\n\nUse installed-extension discovery only when package work needs to compare\nagainst an already installed extension:\n\n- `kora extensions search --environment <environment> --name \"<wildcard>\" --json`\n- `kora extensions search --environment <environment> --description \"<wildcard>\" --json`\n- `kora extensions get <extension-name> --environment <environment> --json`\n\nUse progressive disclosure for installed extensions:\n\n1. Search installed extensions by name, title, or description.\n2. If the needed extension is absent, search available extensions with\n `kora extensions search --environment <environment> --scope available --name \"<wildcard>\" --json`\n or `--description \"<wildcard>\"`; use the returned `nextCommands.install`\n only when the user explicitly wants an install/deployment operation.\n3. Once one installed extension is selected, search inside it:\n `kora extensions search <extension-name> --environment <environment> --kind function --description \"<wildcard>\" --json`.\n The `--kind` value can be `function`, `tool`, `skill`, `function-provider`,\n or `tool-provider`. Use `--name` for exact or wildcard names and\n `--description` for intent/topic search.\n4. Fetch the exact contract only for the selected function/tool/skill:\n `kora extensions get <extension-name> --environment <environment> --function <name> --json`.\n\nFor a ready installed extension, use `kora extensions invoke <extension-name>\n<function-name> --environment <environment> --input @input.json --yes --json`\nonly when the package task explicitly needs to compare or inspect current\ninstalled behavior. Do not use it as package validation, install setup, or a\nreplacement for `kora extensions validate`.\n\nAfter publish in the product chat surface, read `kora-product-ui` and route\ninstallation/setup to its Extensions settings destination. `kora-product-ui`\nowns exact Platform UI routes.\n\nDo not mix package authoring with install/configuration changes. In product\nchat, route install, grant, enable, disable, delete, and configure actions to\nSettings. In an external terminal-agent context, use the full `kora` CLI only\nwhen the user explicitly asks for those deployment operations and the CLI is\nauthenticated to the target deployment.\n\n## Minimal Function Package\n\nUse this shape when the extension adds a stable callable capability to an\ninstalled environment, such as normalizing a record, generating a summary, or\nwrapping a safe API call.\n\n```text\nextensions/lead-helper/\n extension.yaml\n src/index.ts\n```\n\n```yaml\napiVersion: kora/v1\nkind: ExtensionPackage\nmetadata:\n name: lead-helper\n description: Lead utility functions for workflow service nodes.\nspec:\n version: 0.1.0\n entrypoint: src/index.ts\n```\n\n```ts\nimport { Type, type ExtensionHost, type Static } from \"@kora/extension-sdk\";\n\nconst LeadInput = Type.Object(\n { company: Type.String({ minLength: 1 }) },\n { additionalProperties: false }\n);\ntype LeadInput = Static<typeof LeadInput>;\n\nexport default function extension(kora: ExtensionHost) {\n kora.registerFunction({\n name: \"summarizeLead\",\n description: \"Summarize a lead record for follow-up.\",\n input: LeadInput,\n output: Type.Object({ summary: Type.String() }, { additionalProperties: false }),\n async run(input) {\n const lead = input as LeadInput;\n return { summary: `${lead.company} should be followed up.` };\n }\n });\n}\n```\n\nBuild and publish it with:\n\n```sh\nkora extensions validate extensions/lead-helper --json\nkora extensions publish extensions/lead-helper --json\n```\n\n## Common Extension Shapes\n\n- Static function package: registers `registerFunction` for workflow service\n nodes and agents to call after install.\n- Agent tool package: registers `registerTool` when agents should see a\n concrete tool with a fixed schema.\n- Dynamic function provider package: registers `registerFunctionProvider` when\n workflow-callable functions depend on install settings, secrets, storage, or\n an external catalog discovered at runtime.\n- Dynamic tool provider package: registers `registerToolProvider` when agent\n tools depend on install settings, secrets, storage, or an external catalog\n discovered at runtime.\n- Opposite-surface callable: set `exposeAsTool: true` on an individual function\n or function-provider result, or `exposeAsFunction: true` on an individual tool\n or tool-provider result. Both default to false; do not put these flags on the\n provider, manifest, install, Operation, or agent configuration.\n- Event descriptor package: registers `registerEvent` when an installed\n extension wants workflow trigger resources to bind to an external event. The\n descriptor defines the event name, payload schema, optional selector schema,\n optional selector-summary redaction fields, and optional managed-provider\n metadata. Managed Composio built-ins use a permissive object payload schema\n because described provider payloads can differ from actual deliveries. The\n descriptor is metadata only; it does not create a callback URL, register a\n webhook handler, start a workflow, or make the extension aware of workflow\n definitions.\n- Settings-backed connector: registers `registerSettingsView` plus functions to\n test credentials, save setup state, or open an external setup URL. Use\n `secrets` permission for credentials and keep setup in Settings. Call\n `kora.configureSetup({ required: true })` when setup must complete before\n workflow runtime use. Required setup stays blocked until a setup-safe settings\n function or callback completes setup and calls `ctx.setup.markReady()`.\n Disconnect/reset paths that invalidate shared external credentials must call\n `ctx.setup.markRequired()`; use `ctx.setup.markRequired({ scope: \"artifact\" })`\n only when invalidation is specific to the current package artifact.\n- Callback connector: registers `registerCallback` when an external service\n must call Kora back. Use `callbacks` permission and callback helpers for URLs,\n state, metadata, and HMAC verification. Mark only callbacks that are part of\n required setup as `setup: true`; normal webhook/action callbacks should not be\n setup-safe.\n- Scheduled extension: registers `registerSchedule` for recurring extension\n work. Use `schedules` permission and do not start unmanaged background loops.\n- Skill package: registers `registerSkill` and includes\n `skills/<root>/SKILL.md` when the installed extension should provide bundled\n runtime skills.\n\n## Validation Summary\n\n`kora extensions validate <path> --json` is the package preflight. It checks:\n\n- package file safety and size limits, manifest shape, and entrypoint existence;\n- SDK-typed TypeScript source and registration loading through the trusted\n runtime;\n- registration schema shape and cross-references, registered skill files, static\n `outputPersistence` values, registered handler presence, and Ajv-compiled JSON\n Schemas;\n- settings-view render output, using in-memory storage, missing secret metadata,\n fake callback metadata, null Cloud context, and blocked network fetch. Render\n handlers must show an unconfigured setup state without contacting external APIs.\n\nDynamic function and tool providers are validated for registration shape at\npackage validation time. Their runtime `list` output is validated when Platform\nneeds to populate a missing provider-owned capability surface in the install\nregistration snapshot. Discovery is cache-first; empty provider `list` results\nare rejected and not persisted.\n\n`kora extensions publish <path> --json` runs the same package validation\nbefore storing an immutable published package. Publish is the strong\nserver-side gate, not just a file upload. Use it only after validation succeeds\nand the user wants a package they can install.\n\nPackage validation proves the extension package loads and registers valid\nmetadata and that registered settings views return valid declarative JSON. It\ndoes not prove every external API path, credential, OAuth callback, or dynamic\nprovider tool succeeds at runtime. Test external behavior through Settings,\ncallbacks, capability discovery after setup, and extension-backed workflow-node\ntests after install.\n\n`kora test node <workflow-name> <node-id> --workspace <dir> --input @input.json --json`\nvalidates and executes workflow service-node code after an extension is\ninstalled and a service node is bound to an operation that uses it. It does not\nvalidate raw extension package source by itself.\n\n## Authoring Rules\n\n- Keep package source outside workflow release source.\n- Validate before publishing.\n- Publish before the user installs through Settings.\n- Ask the user to review and grant only permissions within the package-declared\n limits in Settings.\n- For settings views, define shared button constants and pass them both in\n static `registerSettingsView({ submit, buttons })` metadata and in the\n declarative JSON returned from `render`.\n- Use settings view `description`, short `blocks`, field `description`, and\n text/textarea `placeholder` values for setup guidance. Keep labels short and\n mark required fields with `required: true` instead of writing \"required\" into\n the label.\n- Do not call external APIs from settings view render handlers. Use render for\n local setup/status display, and use settings functions/buttons for external\n test, save, OAuth, or provider actions.\n- Treat Platform setup lifecycle separately from provider-specific status text.\n Settings views may render \"pending\", \"connected\", or provider errors, but\n durable workflow readiness is changed only with `ctx.setup.markReady()` and\n `ctx.setup.markRequired()` from successful handlers. `ctx.setup.markRequired()`\n defaults to install-wide invalidation for shared external credentials.\n- Browser callback completion only tells the Settings panel to refresh; it does\n not make setup ready unless the callback handler itself calls\n `ctx.setup.markReady()` after verifying the provider state.\n- Treat `ctx.actor` as optional. Callback, schedule, lifecycle, and runtime\n hook handlers must be able to run without a user actor, and storage/secrets\n writes are attributed by the host rather than by extension-supplied user ids.\n- Use `outputPersistence: \"ephemeral\"` for bearer-value outputs only.\n- Use operation runtime SDK bindings when workflow service scripts need to call\n installed extension functions.\n\n## Which Reference To Read Next\n\n- `references/manifest-and-entrypoint.md` — manifest, entrypoint, lifecycle\n hooks, domain hooks, registrations, and ephemeral output rules\n- `references/functions-and-tools.md` — static functions, static tools, dynamic\n tool providers, provider result schemas, refresh behavior, and collision rules\n- `references/settings-callbacks-schedules.md` — bundled runtime skills,\n settings views, form fields, buttons, callbacks, OAuth-style state, HMAC,\n schedules, and human-task notifications\n- `references/extension-context.md` — handler context, actor shape, storage,\n secrets, callbacks, locks, schedules, events, audit, same-install function\n invocation, and extension internal isolation\n"
}SHA-256 of public snapshot: 2494b4d2131ced9b7201a9cdaa1602e437f022867ca872789e3951e7b3df9956