ByteChef LogoByteChef
Component Specification

Component

The component definition describes a reusable integration component (its metadata, actions, triggers, and optional connection). Below is an explanation of each method you can use when building a component with the DSL:

  • component(String name) - Builds a new ModifiableComponentDefinition with the specified backend ID. The name is the component ID used internally and in workflow JSON.
  • actions(A... actionDefinitions) - Declares the actions exposed by this component.
  • agentChannels(ModifiableAgentChannelDefinition... agentChannels) - Declares that this component can carry an AI agent's conversation. See Agent channels below.
  • categories(ComponentCategory... category) / categories(List<ComponentCategory> categories) - Assigns UI categories for grouping and discovery in the catalog. See ComponentCategory.
  • connection(ModifiableConnectionDefinition connectionDefinition) - Defines the connection used by actions/triggers. If not set, actions can still run without a connection if they don't require one.
  • customAction(boolean customAction) - If true, enables the Custom Action feature in the UI (typically for REST/OpenAPI‑based connectors).
  • customActionHelp(Help customActionHelp) - Adds help text for the Custom Action. Displayed as a popup in the UI next to the Custom Action.
  • description(String description) - Short description shown in the catalog and tooltips.
  • icon(String icon) - Path or resource name of the SVG icon shown in the UI.
  • resources(String documentationUrl) / resources(String documentationUrl, Map<String, String> additionalUrls) - Links to product documentation and optional additional resources (e.g., FAQ, blog posts, templates).
  • title(String title) - Human‑readable display name (Chicago style) shown in the UI.
  • triggers(T... triggerDefinitions) - Declares triggers available on this component.
  • clusterElements(ClusterElementDefinition<?>... clusterElements) - Declares reusable cluster elements (e.g., AI tools) that the component may expose.
  • version(int version) - Component version number. Increment this when you make breaking changes so existing workflows can continue to use older versions.

Example

private static final ComponentDefinition COMPONENT_DEFINITION = component("textHelper")
        .title("Text Helper")
        .description("Helper component which contains operations to help you work with text.")
        .icon("path:assets/text-helper.svg")
        .categories(ComponentCategory.HELPERS)
        .actions(TextHelperUpperCaseAction.ACTION_DEFINITION);

Agent channels

An agent channel is a way an AI agent can be reached and can answer: a trigger that receives an incoming message and, usually, an action that sends the reply. Declaring one makes your component selectable as a channel on any agent - no change is needed anywhere else in the platform.

The channel contract is three fields. Each end of the channel states where they live on it, in its own vocabulary:

FieldOn the trigger (agentRequest())On the reply action (agentReply())
conversationIdpath into the trigger's output identifying who to answer. Defaults to "conversationId"the action property that addresses the reply. No default - omit it when the reply is a synchronous response and needs no address
messagepath into the trigger's output holding the incoming text. Defaults to "message"the action property the agent's answer is written to. Defaults to "message"
attachmentspath into the trigger's output holding incoming files. No default - omitting it means this channel carries no attachmentsthe action property carrying outgoing files. Reserved; not wired yet

Because the request side defaults to the contract's own names, a trigger whose output already is the contract (build it with ComponentDsl.agentChannelRequest()) needs nothing but a bare agentRequest(). A trigger with its own payload shape spells the paths out, dots included - e.g. .conversationId("message.chat.id").

Pair them on the component with agentChannel(name, trigger[, replyAction]). The name is the channel's stored key and must be unique across all components:

// trigger
public static final ModifiableTriggerDefinition TRIGGER_DEFINITION = trigger("newChatRequest")
        .title("New Chat Request")
        .output(...)
        .agentRequest(agentRequest().attachments(ATTACHMENTS))
        .webhookRequest(ChatNewRequestTrigger::getWebhookResult);

// reply action
public static final ModifiableActionDefinition ACTION_DEFINITION = action("responseToRequest")
        .title("Response to Request")
        .agentReply(agentReply().attachments(ATTACHMENTS))
        .perform(ChatResponseToRequestAction::perform);

// component
private static final ComponentDefinition COMPONENT_DEFINITION = component("chat")
        .title("Chat")
        .agentChannels(
                agentChannel("chat", ChatNewRequestTrigger.TRIGGER_DEFINITION,
                        ChatResponseToRequestAction.ACTION_DEFINITION)
                                .title("Chat")
                                .approvalChannel("chat"));

Optional on agentChannel(...):

  • title(String title) / description(String description) - How the channel is labelled in the agent UI. Defaults to the component's own title, which is wrong whenever one component exposes a channel that is not the whole component (Twilio's channel is titled "Twilio (WhatsApp)").
  • approvalChannel(String elementName) - Which of this component's APPROVAL_CHANNELS cluster elements a human approval request is delivered through on this channel. Omit it and the channel simply cannot carry approvals.
  • triggerParameters(Map<String, Object> triggerParameters) - Parameters pinned onto the generated trigger node, for a trigger whose output shape depends on its own input.

Optional on agentReply():

  • channelParameter(String rowKey, String property) - A value the user configures on the channel itself is copied into property on every reply. Twilio's number becomes the reply's From this way; rowKey must name a property the paired trigger declares.
  • fixedParameter(String property, Object value) - A reply parameter pinned by the declaration, e.g. useTemplate = false.

Everything is validated when the component loads: a path or property name that the paired trigger or action does not declare fails fast, rather than producing an agent that silently replies nowhere. A trigger that receives an event it should not act on declines by returning an empty collection from its webhook handler - the agent run never starts.

How is this guide?

Last updated on

On this page