Delivering & Managing Custom Integrations
Deliver custom integrations through packs (Git/OCI sources), and manage installed integrations
Manual tarball upload has been removed. Custom integrations are now delivered exclusively
through packs — a Git or OCI source your CI/CD publishes to, installed from your org's pack
catalog. Publish your .bundle.tar.gz inside a pack instead of uploading it directly. See
Pack sources and
Packaging a custom integration in a pack.
Custom Integration Scopes
Integration identities reserve three scopes. Organization uploads are the currently supported custom-integration path:
| Scope | Origin | Visibility | How it's delivered |
|---|---|---|---|
First-party (org:scrydon:) | Baked into the Docker image | All organizations | Shipped with Scrydon releases |
Platform (org:platform:) | Reserved for a platform-scoped pack | All organizations | Not currently enabled; requires dedicated platform-owned artifact storage |
Organization (org:{orgId}:) | Org pack source | Single organization | Org admin installs from the org's pack catalog |
Every organization-installed tool has a platform microVM floor. Only exact reviewed code shipped by Scrydon may use the approved Worker Thread tool backend; a matching vendor name never grants uploaded code that trust. A custom tool is selectable by an isolated Agent only while the exact Runtime Plane backend is qualified and attested.
Delivering via a pack source
Publish your built .bundle.tar.gz as an integration content entry inside a pack, to a Git
or OCI source your CI/CD controls. See
Packaging a custom integration in a pack.
Go to Settings > Platform > Integrations → the Custom tab (direct URL:
/settings/platform/integrations#custom) and register your pack source. Sources sync packs
into your org's pack catalog. See Pack sources.
Synced custom integrations appear in Add Integration under From your pack catalog — adding one installs and activates it immediately (your explicit install is the review). A cosign-signed source is also trusted for non-interactive installs; unsigned automated syncs land as Pending Review.
When a new artifact is published, the card shows an Update badge; clicking it takes you to Settings → Platform → Packs where you can review workflow impact and apply the update. See Pack version management.
What Happens on Install
When a pack carrying an integration entry is installed, the platform runs the same bundle
pipeline it always has:
Extracts the .tar.gz with security checks:
- No symlinks allowed
- No absolute paths
- No path traversal (
../) - No device, FIFO, duplicate-path, or unsupported archive entries
- A bounded entry count and bounded decompression output
- Only allowed file extensions (
.js,.js.map,.json,.svg,.png,.jpg) - A required
dist/index.jsentry point - Maximum extracted size: 100 MB
Validates manifest.json against the ManifestSchema (Zod):
- Vendor ID format:
/^[a-z][a-z0-9-]*$/ - Tool IDs reference valid vendor prefixes
- Auth credential types are valid
- No duplicate product IDs
- Required fields are present
Writes the artifact to blob storage:
00_organization/integration-bundles/{vendorId}/{version}/bundle.tar.gzRegisters the integration with the vendor ID, version, manifest JSON, storage key, SHA-256
hash, and scope in the org's installed-integration record (integration_bundle).
Managing Installed Custom Integrations
Statuses
| Status | Meaning |
|---|---|
| Active | Custom integration is available for use in workflows |
| Disabled | Custom integration is installed but not available (manually disabled) |
| Pending Review | Installed from an unsigned, non-interactive pack sync — awaiting review (sign the source or install explicitly to activate) |
| Failed | Custom integration failed to load at runtime (check error message) |
Enable / Disable
Enable or disable a custom integration's products from the vendor detail dialog under Settings > Platform > Integrations. Disabling removes it from the workflow editor but does not delete the stored files.
Versioning
Publish a new pack version to update the integration. The platform stores each version by
{vendorId}/{version}/, so multiple versions can coexist; the live version is the semver-max
active one (or the pinned version if your org pinned one — see
Pack version management).
Uninstalling or superseding a custom integration will break any workflows that reference its tools. Verify no workflows depend on it first.
Catalog and Execution Sequence
When the platform starts:
- Scan first-party bundles — parse
manifest.jsonfrom/app/bundles/(Docker image) - Scan platform bundles — parse manifests from platform storage
- Scan org bundles — parse manifests from each organization's storage
- Populate Manifest Catalog — metadata only, no vendor code loaded
- Publish dynamic readiness — the Runtime Plane reports whether the exact digest-pinned vendor profile has current candidate and deployment proof
- Admit on demand — the compiler exposes a custom Agent tool only when its verified SHA-256 source and exact backend pass the security floor
- Execute once — the trusted broker revalidates tenant, environment, connection, source, policy, and binding revisions, then starts a fresh
vendor_bundlemicroVM
Custom integration code is never loaded on the Agentic/API host at boot. The platform reads
manifest metadata only. At execution, the active archive bytes are re-hashed, transferred through
a one-use sealed grant, unpacked inside the vendor guest, and deleted with that single-use VM.
The Agent's own agent_turn VM never receives the archive or reusable credentials.
Agent tool readiness
For an isolated Agent, a non-Scrydon tool is available only when all of these are true:
- the active archive has a verified SHA-256 identity and still matches the compiled source revision;
- the authenticated Runtime Plane supports the
vendor_bundlecontract; - runner, broker, and enforcer images are digest-pinned;
- a schedulable Kata/KVM substrate is observed;
- signed exact-candidate and deployment proofs match the configured images, profile, and evidence digests;
- actual-request egress, outbound DLP, and audit are ready; and
- the encrypted one-use grant store is ready.
Any missing condition produces a typed remediation error. The platform never degrades an organization-installed Agent tool to a Worker Thread.
Organization Policies
Organization policies (configured by admins) govern custom integration behavior:
Execution Policy
{
"maxConcurrentExecutions": 10,
"maxTimeoutSeconds": 30,
"allowedCapabilities": ["llm", "stt", "tools"]
}Governance Policy
{
"allowedVendorScopes": ["scrydon", "platform"],
"blockedVendorIds": []
}blockedVendorIds— vendor IDs blocked from installing (enforced on pack install)allowedCapabilities— which capability types are permitted
The legacy allowOrgUploads / requireApprovalForUploads fields governed the removed manual
upload flow and no longer have any effect. Whether a pack-delivered integration activates on
install is governed by source signing and the explicit-install policy (see the delivery steps
above), not these fields.
Package Format
Every custom integration is packaged as a .tar.gz archive with this structure:
{vendorId}-{version}.bundle.tar.gz
├── manifest.json (vendor metadata, JSON Schemas, UI definitions)
├── dist/
│ └── index.js (compiled, minified ESM; all dependencies inlined)
├── meta/ (automatically generated)
│ ├── sbom.cdx.json (CycloneDX 1.6 SBOM)
│ └── metafile.json (esbuild dependency graph)
└── assets/ (optional)
└── icon.svg, icon.png (vendor/product icons)SBOM Generation
Every custom integration artifact automatically includes a CycloneDX 1.6 Software Bill of Materials (SBOM) at meta/sbom.cdx.json. The SBOM is generated during sdk-authoring integrations build with no additional tools or configuration required.
What's in the SBOM
The SBOM lists every NPM package that esbuild bundled into dist/index.js:
- Package name and version — exactly what's in the bundle
- License — SPDX license identifier from
package.json - Package URL (purl) — machine-readable identifier (
pkg:npm/zod@3.24.0) - Evidence — file paths proving the package is actually bundled (tree-shaken code is excluded)
The SBOM only includes packages that esbuild actually bundled. If a dependency was tree-shaken away, it won't appear — making the SBOM an accurate reflection of what ships in your bundle.
How it's generated
During sdk-authoring integrations build, the CLI:
- Runs esbuild with
metafile: trueto capture all input files - Extracts unique NPM packages from
node_modules/paths in the metafile - Reads each package's
package.jsonfor name, version, license, and description - Serializes everything to CycloneDX 1.6 JSON
- Writes the result to
meta/sbom.cdx.jsonalongside the esbuild metafile
No external tools or dependencies are required — the generation is built into the CLI.
How admins use it
After installing a custom integration, the Dependencies tab in the vendor detail dialog shows the SBOM component count in the tab header and lists all auto-detected packages alongside declared dependencies. See Custom Integration Review Before Activation for the full review workflow.
Compliance
The CycloneDX format is widely supported by compliance tools. For environments that require SPDX, convert using:
cyclonedx-cli convert --input-file meta/sbom.cdx.json --output-file sbom.spdx.json --output-format spdxjsonThe raw esbuild dependency graph is also available at meta/metafile.json for debugging. You can visualize it at esbuild.github.io/analyze.
Custom Integration Review Before Activation
After a custom integration is installed, administrators can review its contents before enabling it for the organization. The vendor detail dialog provides a structured review experience across multiple tabs.
Capabilities Tab
Shows all products, tools, triggers, and runtime capabilities the custom integration provides. Administrators can enable or disable individual blocks from this tab. Intelligence capabilities (LLM, STT, TTS, Embedding) display model counts and support allowlist-mode policy configuration. See Capabilities for details.
Dependencies Tab
The Dependencies tab displays two complementary views of the custom integration's dependency tree:
- Declared dependencies — Hand-authored entries from
defineProduct({ dependencies: [...] })that include a human-readablereasonfor each dependency. - Auto-detected dependencies (SBOM) — The full set of NPM packages that esbuild bundled into
dist/index.js, extracted frommeta/sbom.cdx.json. Each entry shows the package name, version, license, and a machine-readable package URL (purl).
The tab header shows the total SBOM component count so administrators can quickly gauge the custom integration's dependency footprint. Organization dependency policies (risk levels, blocklists, post-install script blocking) are evaluated against both declared and auto-detected dependencies.
If a dependency is blocked by the organization's policy, it is flagged in the Dependencies tab with the reason (e.g., "Risk 'high' exceeds max 'medium'" or "Has post-install scripts"). Blocked dependencies prevent the custom integration from being activated until the policy is adjusted or the .bundle.tar.gz is rebuilt without the offending package.
Setup Tab
Shows the vendor's authentication configuration (OAuth, API Key, Bot Token, or None) and allows administrators to configure credentials before enabling the vendor's capabilities.
Storage Layout
First-party (baked into Docker image):
/app/bundles/{vendorId}/dist/index.js
Platform uploads:
{platformPrefix}/integration-bundles/{vendorId}/{version}/bundle.tar.gz
Org uploads:
{storageKeyPrefix}/00_organization/integration-bundles/{vendorId}/{version}/bundle.tar.gzTroubleshooting
Install fails with "Invalid manifest"
Run the CLI validator locally before publishing the pack to see detailed errors:
bunx @scrydon/sdk-authoring integrations test --level staticCommon issues:
- Vendor ID contains uppercase or special characters
- Tool ID doesn't start with the vendor ID prefix
- Missing required fields (
id,name,version,icon,auth) - Zod schema uses unsupported types (the extractor converts Zod → JSON Schema)
Custom integration status shows "Failed"
Check the error message in the vendor detail dialog (and server logs). Common causes:
dist/index.jshas a syntax error- Default export is not a
defineVendor()result - Missing
export defaultstatement - Runtime import fails (ensure all deps are bundled — esbuild should inline them)
Tool doesn't appear in the workflow editor
- Verify the pack that carries the integration is installed (Settings > Platform > Packs) and its version is active
- Verify the product is enabled for your organization in Settings > Platform > Integrations
- Check the block's
category— it must be"tools","blocks", or"triggers"to appear in the correct palette section
Build warns that block tool configuration will be omitted
tools.config.tool and tools.config.params are functions, so they cannot be represented in manifest.json. Replace dynamic routing with tools.toolSelector, expose direct parameters as block inputs, and move any remaining parameter coercion into the tool's execute() function. Do not ignore this warning: an installed workflow block only has the JSON-safe manifest definition at serialization time.