ExecWarden Docs

Custom tools

Package an API as governed agent tools.

Capability packages are registry-owned integration artifacts. They declare actions, schemas, secrets, runtime code, and policy hints, then expose agent-facing tools named pkg:<packageId>:<action>.

What a Package Provides

Use a package when the valuable tool is a private API or team-owned integration that should feel like one governed capability, not a pile of endpoint credentials. Start with one action, one declared secret, and one observable result.

Registry-owned

Packages are stored as workspace registry data, not app-bundled Node imports.

API-key auth

Declare package-local secret names in the manifest and configure values after creation.

Sandboxed runtime

JavaScript runs in the Wasm/QuickJS sandbox. Wasm artifacts run as WASI command modules.

Hosted UI

Attach static uiAssets outside the manifest. Published bundles render from isolated package UI origins.

Policy-gated tools

Published actions expose agent-facing tool names such as pkg:<packageId>:<action>; canonical grants use the package capability definition id.

Minimal Manifest

A manifest is the package contract: what the tool is called, which secret names it may read, what runtime file runs, and what input shape the agent must provide. Keep the first package boring: one read action with one small schema.

Pick the actionChoose one operation a human already understands, such as read current user, list tickets, or preview one internal record.
Declare secrets by nameThe manifest names secrets; workspace setup stores the values later. Do not put provider tokens in source code or docs.
Describe the inputUse the narrowest schema that lets ExecWarden reject accidental agent calls before runtime code runs.
Choose the default modeUse readOnlyHint only as a default-mode hint. The actual authority comes from canonical grants.
{ "packageId": "linear-lite", "name": "Linear Lite", "description": "Read Linear viewer data through a package-local API key.", "version": "0.1.0", "auth": { "type": "api_key", "secrets": [{ "name": "linear_api_key", "label": "Linear API key" }] }, "runtime": { "kind": "javascript", "entry": "guest.js" }, "actions": [{ "id": "viewer.get", "name": "Get viewer", "description": "Read the authenticated Linear viewer.", "readOnlyHint": true, "inputSchema": { "type": "object", "properties": {}, "additionalProperties": false } }] }

Runtime Code

A JavaScript package registers source code separately from the manifest. The runtime receives the selected request and can read only the package-local secrets declared above.

const key = gateway.secrets.get("linear_api_key"); const res = await fetch("https://api.linear.app/graphql", { method: "POST", headers: { authorization: key, "content-type": "application/json" }, body: JSON.stringify({ query: "{ viewer { id name email } }" }) }); return { ok: true, data: await res.json() };

Register and Publish

Package authoring is done through the gateway MCP management tools. Store a draft, configure its workspace-owned secrets, test a draft action, then publish the snapshot that callers can be granted.

ValidateCheck the manifest and runtime shape before writing registry state.
Create draftStore the package contract and runtime source in the workspace registry.
Set secretsConfigure values for the declared secret names outside source code.
TestRun the draft action with real parameters and inspect the structured result.
PublishPromote the tested snapshot so grants can expose it to an Agent identity, session, or workflow.
gateway_capability_packages_validate({ manifest, runtime, uiAssets }); gateway_capability_packages_create({ manifest, runtime: { kind: "javascript", source: runtimeSource }, uiAssets }); gateway_capability_packages_set_secret({ packageId: "linear-lite", secretName: "linear_api_key", value: "lin_api_..." }); gateway_capability_packages_test({ packageId: "linear-lite", action: "viewer.get", params: {} }); gateway_capability_packages_publish({ packageId: "linear-lite" });

Grant the Published Tool

Publishing does not expose the package to every agent. A caller still needs an Agent identity, session, or workflow grant for the exact package action.

CallerChoose the Agent identity, hosted session, or workflow that should see the package action.
ActionGrant the exact package capability, such as pkg:<workspace-segment>:linear-lite:viewer.get.
ModeUse Allow for read-only package actions; use Ask for package actions that can change provider state.
ScopeKeep scope empty only when the action has no useful resource boundary. Prefer package-declared fields when available.

Ask the User Before Continuing

A package action can return a userInputRequest instead of completing immediately. ExecWarden stores the request, shows it to the workspace, and resumes the source session after a person answers. Use this when an integration needs judgment, a reason, a choice, or an explicit continue signal before it calls the provider. Open Human Input for the full lifecycle, MCP response shape, and trust-boundary notes.

resumePause until a person explicitly resumes the session.
free_textCollect a short text answer, such as a reason, ticket id, or release note. A submit followup can bind the text into one followup parameter.
single_choiceAsk the user to pick one option. A selected choice can run a same-package followup action.
multi_choiceCollect multiple choices. Followup execution is intentionally not supported for multi-choice in the first slice.
return { ok: true, userInputRequest: { title: "Review production change", summary: "Terminate instance i-123 in us-east-1?", input: { kind: "single_choice", choices: [ { id: "approve", label: "Terminate", style: "danger", followup: { capability: "pkg:aws-admin:instances.terminate.commit", params: { instanceId: "i-123", region: "us-east-1" } } }, { id: "reject", label: "Cancel" } ] } } };

Approve/reject prompts are approvals: if a single-choice request has exactly approve and reject choice ids, it appears in the approvals API and UI, and answering it is the approval decision. Generic prompts still return pendingUserInputId; MCP clients see pending_user_input for generic input and pending_approval for approval-shaped input.

Manage Packages Through MCP

Package management tools are authoring controls, not tools every agent should see. Grant them only to a package-authoring identity or hosted session. Ordinary task identities should receive the published package actions, not package registry management.

gateway_docs_get gateway_examples_list gateway_examples_get gateway_capability_packages_validate gateway_capability_packages_create gateway_capability_packages_update gateway_capability_packages_list gateway_capability_packages_get gateway_capability_packages_set_secret gateway_capability_packages_test gateway_capability_packages_publish gateway_capability_packages_disable gateway_capability_packages_delete

Package-Owned Storage

Packages that need durable integration state should bring or configure their own storage. ExecWarden keeps workspace context, package-local secrets, runtime isolation, policy, approvals, and audit boundaries; the package owns its schema and provider choice.

Use it forSync cursors, external id mappings, webhook dedupe, idempotency, and staged mutations before irreversible provider writes.
Runtime APIProvider and DBaaS calls use fetch(...). Package-local credentials use gateway.secrets.get(...).
Isolation rulePrefer one database or token per workspace when possible. In shared databases, keep workspace_id in every table key and every read/write predicate.
GuideOpen Package Storage for the staged-mutation lifecycle, registration flow, and Turso/Neon/Cockroach notes.
Next questionUse Human Input when the package needs a reason, choice, approval, or resume signal before it commits the provider action.