ByteChef LogoByteChef
Embedded

Component Kit

One API that exposes a connected user's integrations twice - as actions your code calls, and as tools a language model calls.

AI ComponentKit is one API for AI-native products: it exposes what a connected user has connected as operations you can execute under that user's own credentials. One API covers every integration, so your product acts through the user's ByteChef connections without you writing per-integration glue.

It exposes them twice, for two different callers - actions for your code, tools for a model - and the difference is worth getting straight before you pick an endpoint.

Actions and tools

An action is the unit ByteChef executes: one operation on one component, such as Slack's sendChannelMessage. Your code names it, supplies its input, and gets the result.

A tool is an action projected for a language model. A component publishes selected actions as tools; the platform gives each one a flat name, a description, and a JSON Schema, hands that catalogue to your model, and the model chooses.

The execution underneath is the same, and so is the connection. The caller is not, so the two surfaces differ in more than their URL:

ActionTool
Who chooses itYour code, before the callThe model, at inference time
EndpointPOST /{externalUserId}/components/{componentName}/versions/{componentVersion}/actions/{actionName}POST /{externalUserId}/tools
AddressComponent, version, and action name, in the pathOne flat name in the body - SLACK_SEND_CHANNEL_MESSAGE
CoverageEvery action the component definesOnly the actions the component publishes as tools
VersioningPinned in the pathResolved server-side, always the component's current version
DiscoveryNone - your code already knows what it is callingGET /{externalUserId}/tools, scoped to that user
Request body{ "input": { ... } }{ "name": ..., "parameters": { ... } }
Response{ "result": ... }The result, unwrapped
File inputBinary and form-data uploads supportedNot supported

The rule of thumb: if a model is choosing, use tools; if your code has already decided, call the action.

Both live under /api/embedded/v1, authenticate with an embedded API key (Authorization: Bearer), and take an X-Environment header selecting DEVELOPMENT, STAGING, or PRODUCTION. Neither ever sees the user's credential: it is resolved server-side from the connected user, and if that user has more than one instance of the same integration, the optional X-Instance-Id header picks which.

The same tool catalogue is also reachable over MCP: an MCP Server wraps the same actions - and, unlike ComponentKit, whole workflows - for agents that speak that protocol. ComponentKit is the plain-HTTP path, MCP is the protocol path; pick whichever your agent already talks.

Listing a user's tools

GET /tools returns the tools grouped by the component they belong to, each already in function-calling shape:

{
  "slack": [
    {
      "type": "function",
      "function": {
        "name": "SLACK_SEND_CHANNEL_MESSAGE",
        "description": "Sends a message to a public channel.",
        "parameters": "{\"type\":\"object\",\"properties\":{ ... }}"
      }
    }
  ]
}

Two things about that shape are worth knowing before you wire it up:

  • parameters is a JSON Schema carried as a string, not a nested object. Parse it before handing it to your model client.
  • A tool name is an address, not a label. It is the component name uppercased, then the action name in SCREAMING_SNAKE_CASE - sendChannelMessage on slack becomes SLACK_SEND_CHANNEL_MESSAGE. Executing a tool splits that name back apart to find the component and the action, which is why the call carries no component field and no version.

Narrow the catalogue with the categories, components, and tools query parameters. Useful when a user has connected far more than a given conversation should be allowed to reach.

What ends up in the catalogue

  • Only actions published as tools. A component opts its actions in one at a time; an action it does not opt in never appears in GET /tools, though your own code can still call it as an action.
  • Only integrations that user has connected. The catalogue is derived from that user's own integration instances, so it differs per user and grows the moment they connect something new - with no redeploy on your side.
  • Actions, not workflows. To let an agent run a whole workflow, expose it through an MCP server or trigger it with an App Event.

Running a tool

POST /api/embedded/v1/{externalUserId}/tools
Authorization: Bearer <api-key>
X-Environment: PRODUCTION
Content-Type: application/json

{
  "name": "SLACK_SEND_CHANNEL_MESSAGE",
  "parameters": { "channel": "#general", "text": "Deploy finished." }
}

The response is the provider's own response, returned as-is.

Calling an action

When your code has already decided what to run, address the action directly. The input goes under input, and the result comes back wrapped in result:

POST /api/embedded/v1/{externalUserId}/components/slack/versions/1/actions/sendChannelMessage
Authorization: Bearer <api-key>
X-Environment: PRODUCTION
Content-Type: application/json

{
  "input": { "channel": "#general", "text": "Deploy finished." }
}

This is also the surface to use when an operation takes a file: set bodyContentType to BINARY or FORM_DATA in the input and the endpoint resolves the referenced content into a file entry before the action runs. The tools endpoint has no equivalent, so file-bearing operations stay in your code rather than in the model's hands.

ComponentKit in the Sample App

The Sample App includes a "ComponentKit Playground" that calls a single action directly, and a tool-based AI chat page that runs the full catalogue-and-choose flow.

Sample projects

How is this guide?

Last updated on

On this page