Use an ingredient pack when a recipe needs a reusable operation against an outside system: an API request, GraphQL query, enrolled connector method, local command, or realtime subscription. The ingredient says how one operation works; the pack supplies its installation, connection, grant, and uninstall boundary.
If the work is pure computation, use a transform. If it sequences operations into an outcome, write a recipe. Keep credentials out of both: they belong to a named connection.
#Start in the Pack editor
Open Kitchen → Ingredient pack. The editor always produces a pack, even for one operation. Treating a small integration as a minimal pack gives it the same review, grant, and lifecycle rules as a larger catalog.
The editor has five sections:
| Section | Decide here |
|---|---|
| Overview | Draft title, durable slug, and review summary |
| Setup | Connection-backed API or delegated local CLI |
| Operations | Callable operations, bindings, arguments, risk, and approval |
| Data fields | Canonical entity fields, mappings, and privacy labels |
| Publish | Pack identity, dependencies, local preview, grants, and install |
Save early. A saved draft receives its own Kitchen URL and appears in the draft picker; a fresh edit makes the previous validation result stale until you save again.
#1. Name the capability
Give the draft a human title and a stable lowercase slug. The slug becomes part of every installed operation id, so prefer the system or capability name over a temporary project name. Renaming it later creates a different capability from the point of view of recipes and grants.
In Publish, give the pack its own slug, description, kind, service kind, and search tags. A useful description answers three questions: what outcome does this add, which system does it contact, and whether anything runs in the background.
#2. Choose the execution surface
In Setup, choose the smallest surface that can perform the operation.
Connection is for HTTP, GraphQL, and connector methods. Declare the base URL or endpoint shape and the connection the pack expects. The draft describes requests; it does not carry an API key, OAuth token, cookie, or password. The server injects the enrolled credential only at call time.
CLI delegated is for a command already available on the server host. Name the executable and a readiness probe. Each operation builds an argument vector, not an interpolated shell command. Keep user-controlled values in typed argument slots and never turn one into executable code.
Records is for a pack that needs to keep its own business rows — a job board,
a course roster, an order ledger — rather than read someone else's. The rows live
in your server's own encrypted database, and the pack exposes them as ordinary
operations, so a recipe calls job.search exactly the way it would call a vendor
API. There is no credential and nothing leaves the machine.
Records is deliberately bounded, and the bounds are the product rather than a first version to grow out of. A pack declares business objects onto a fixed row shape — a set number of text, number, exact-decimal, date, true/false, and reference slots per object — and gets a closed set of operations over them: create, read one, read many, search, count, update, insert-or-update, and delete. There is no SQL, no schema of your own, and no custom index. When one object runs out of slots you declare a second object and relate the two, which is ordinary data modelling.
Three properties are worth designing around from the start. Every change is checked — an update or delete must state the row version it expects, so two people editing the same row cannot both silently win. Searching is bounded — you declare which fields may be filtered and sorted, and a query too broad to answer is refused with guidance rather than quietly grinding. Changing your row shape later is a migration, reviewed and run in steps, so it is worth spending a little time on the shape before you publish.
If the required provider connection or executable is absent, preview and installation should say so. Do not make a draft appear portable by baking a machine-specific secret or path into it.
#3. Declare operations
Add one card per callable operation. Group related cards into a family, then give each operation a stable name and a plain-language description. Recipes refer to the resulting installed operation id, so a name change is a breaking change.
The editor has structured forms for the common binding kinds:
| Binding | Use it for |
|---|---|
| REST | An HTTP method and path template, with fixed and caller-supplied query or header fields |
| GraphQL | A query or mutation plus its variables and result shape |
| CLI invocation | An executable argument vector and bounded output contract |
| Method call | A method exposed by an enrolled connector |
Webhook, queue, and push-channel bindings use the advanced JSON form. They are specialized realtime surfaces; use them only when the provider cannot be modeled as an ordinary request.
For every operation:
- declare each caller-supplied argument and its type;
- mark an argument as target-affecting when changing it changes the person, record, file, or destination the approval applies to;
- choose an honest risk tier —
read,write,admin, ordestructive; - choose
never,ask, oralwaysfor approval; - mark the card reviewed only after checking its resolved target, required scopes, editable arguments, pagination, and output mapping.
The Reviewed checkbox is an author attestation, not a bypass. Server validation and the live policy gate still decide whether the artifact can be installed and whether a call can execute.
#4. Map data deliberately
An action-only pack may need no entity schema. A data catalog should use Data fields to turn vendor-shaped responses into stable fields recipes can understand.
For each field, declare its entity, vendor path, type, request/response use, and source operation. Mark it optional when the provider legitimately omits it. Apply a PII label when it contains a name, email, phone number, address, or other supported privacy class; the review summary calls those fields out.
Cross-vendor aliases are semantic promises. Select one only when the field really carries the canonical meaning — not merely because two vendors use a similar label.
#5. Save and read the review
Save persists the draft, validates it on the server, and decomposes it into the exact ingredient, catalog, entity-schema, operation-group, and default-grant artifacts installation would write. The review summarizes:
- operation families and their risk/approval mapping;
- entity-field and PII counts;
- compiled output count;
- path-specific errors and warnings.
Errors block preview and install. A valid review may still carry warnings; read them rather than treating the green status as a substitute for judgment. Any edit invalidates the review until the new body is saved and reviewed.
#6. Preview without testing a write on production
After review passes, select an operation in Publish, enter preview arguments as one JSON object, and choose Preview.
For a connection-backed read, Recued may execute the real request against the enrolled connection, then show a bounded, secret-redacted mapping preview. A write, admin, or destructive operation is never executed by preview: you see the resolved request plan, risk, approval, and auth source instead. Connector and realtime operations may also return a non-executing plan when they cannot be safely sampled.
Preview is intentionally temporary: it does not mutate the draft, persist a sample, or create a normal run audit entry. Exercise the installed operation through a test recipe when you need end-to-end policy and audit proof.
#7. Install locally before publishing
Complete the pack metadata and dependency list. For a connection-backed pack, choose the local access tier and audience shown by the install grant picker, then choose Install.
This action installs the reviewed draft on your server. It is not a marketplace publication, despite living in the editor's Publish section. Verify the installed pack in Discover or Settings, call each read through a test recipe, confirm writes stop at the expected approval, then test uninstall on a server where no recipe still pins the capability.
#8. Publish the pack
Public publication is a separate cloud action. Reserve a free publisher handle,
set the manifest's publisher to that exact handle, and publish a version-2
pack whose contents carries the reviewed composition. The dashboard accepts a
Kitchen handoff when a build provides one, an uploaded JSON file, or a pasted
JSON object.
Packs publish directly rather than entering the recipe review queue, but the cloud still reruns pack and composition validation. Direct publication does not certify the pack, resolve every external pin, or grant anything on an installer's server. Read the pack manifest and publishing guides before submitting.
#Before you share it
- The slug and operation ids are stable and publisher-qualified.
- No secret, token, cookie, local username, or machine-specific path is in the draft.
- Every caller-controlled target field is declared and marked appropriately.
- Risk and approval describe the real consequence of each operation.
- Reads preview successfully; mutations show a plan without executing.
- PII fields and output mappings are accurate.
- Local install, a test recipe, audit, and uninstall all behave as expected.
- The pack version and every dependency pin are intentional.
For the lowered single-operation fields, see the ingredient manifest reference. For the bundle envelope and by-value composition boundary, see the pack manifest reference.