Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .agents/coming-soon-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Two ways something here is hidden, and the tables below mark both:

Both are reversible and neither deletes anything.

**45 whole-page** (20 hidden) · **29 partial** pages (6 with a commented-out section)
**45 whole-page** (20 hidden) · **30 partial** pages (7 with a commented-out section)

---

Expand Down Expand Up @@ -134,6 +134,7 @@ arriving soon was not helping a reader.
| [`/platform/embedded/get-started/quick-start`](/platform/embedded/get-started/quick-start) | Let your users build their own workflows (optional) | rendered |
| [`/platform/embedded/get-started/quick-start/sample-app`](/platform/embedded/get-started/quick-start/sample-app) | What the sample demonstrates | rendered |
| [`/platform/embedded/get-started/tenant-isolated-security`](/platform/embedded/get-started/tenant-isolated-security) | Layer 3: Crypto | rendered |
| [`/platform/embedded/monitor/failures-and-retries`](/platform/embedded/monitor/failures-and-retries) | No replay from your product; **No automatic retry policy** | **1 of 2 commented out** |
| [`/platform/embedded/monitor/workflow-executions`](/platform/embedded/monitor/workflow-executions) | Execution Detail View | rendered |
| [`/platform/settings/ai-providers`](/platform/settings/ai-providers) | What uses activated providers | rendered |
| [`/platform/settings/notifications`](/platform/settings/notifications) | Delivery types | rendered |
Expand Down
94 changes: 47 additions & 47 deletions docs/content/docs/developer-guide/architecture.mdx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@ public class NewComponentComponentHandler implements ComponentHandler {

`@AutoService(ComponentHandler.class)` registers the class with the JDK `ServiceLoader`, which is how
the platform discovers components. A handler discovered this way is instantiated by the platform, not
by Spring, so it has **no dependency injection** everything it needs must be a constant or come from
by Spring, so it has **no dependency injection** - everything it needs must be a constant or come from
the `Context` passed into `perform`.

If your component genuinely needs Spring beans (for example an AI model registry), annotate the
handler with `@Component("newComponent_v1_ComponentHandler")` instead and use constructor injection
handler with `@Component("newComponent_v1_ComponentHandler")` instead and use constructor injection -
Spring-managed handlers are collected by type and merged with the ServiceLoader ones. Keep the
`<componentName>_v<version>_ComponentHandler` bean-name shape; it is the convention every such
handler in the codebase follows. Only a handful of built-in components need this;
`server/libs/modules/components/ai/agent/utils/.../AiAgentUtilsComponentHandler.java` is one example.

### Icon

Find and download a user interface icon in .svg format for your component and place it in `server/libs/modules/components/newcomponent/src/main/resources/assets/newcomponent.svg` the file name has to match the `icon("path:assets/…")` value above.
Find and download a user interface icon in .svg format for your component and place it in `server/libs/modules/components/newcomponent/src/main/resources/assets/newcomponent.svg` - the file name has to match the `icon("path:assets/…")` value above.

The `title`, `description`, and `icon` you set here are exactly what the workflow editor shows when the component is discovered: once the module is on the classpath and the server is running, the component appears in the editor's component panel and can be dropped into a workflow.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ The action definition is used to specify the behavior and UI of an action inside
- `deprecated(boolean deprecated)` - Marks the action as deprecated. Deprecated actions should not be used in new integrations.
- `perform(PerformFunction perform)` - Defines the action logic with access to the configured connection. Several overloads exist for specialized cases (`CallableResponsePerformFunction`, `WebhookResponsePerformFunction`, `StreamPerformFunction`, `WebSocketPerformFunction`), all sharing the same three-argument shape below.
Perform functions receive:
- `Parameters inputParameters` Getter for action properties (values set by the user in the Properties tab).
- `Parameters connectionParameters` Getter for connection properties (if the action uses a connection).
- `ActionContext actionContext` Utilities for implementing logic:
- `encoder` Encode/decode data.
- `file` Work with temporary files (produces/consumes FileEntry).
- `data` Read/write persistent action data between runs.
- `log` Structured logging.
- `json` JSON read/write helpers.
- `http` HTTP client for external calls.
- `event` Publish platform events (e.g. action progress) when needed.
- `Parameters inputParameters` - Getter for action properties (values set by the user in the Properties tab).
- `Parameters connectionParameters` - Getter for connection properties (if the action uses a connection).
- `ActionContext actionContext` - Utilities for implementing logic:
- `encoder` - Encode/decode data.
- `file` - Work with temporary files (produces/consumes FileEntry).
- `data` - Read/write persistent action data between runs.
- `log` - Structured logging.
- `json` - JSON read/write helpers.
- `http` - HTTP client for external calls.
- `event` - Publish platform events (e.g. action progress) when needed.
- `help(String body)` / `help(String body, String learnMoreUrl)` - Adds help text (and optional *Learn more* link) displayed in the UI.
- `properties(P... properties)` - Lists the properties that the action needs to perform its task. Properties are shown in the Properties tab. See [Property](/developer-guide/component-specification/property).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,17 @@ private static final ComponentDefinition COMPONENT_DEFINITION = component("textH

### 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.
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:

| Field | On the trigger (`agentRequest()`) | On the reply action (`agentReply()`) |
|---|---|---|
| `conversationId` | path 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 |
| `conversationId` | path 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 |
| `message` | path 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"` |
| `attachments` | path into the trigger's output holding incoming files. **No default** omitting it means this channel carries no attachments | the action property carrying outgoing files. Reserved; not wired yet |
| `attachments` | path into the trigger's output holding incoming files. **No default** - omitting it means this channel carries no attachments | the 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")`.
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:

Expand Down Expand Up @@ -83,4 +83,4 @@ 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.
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.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ The trigger definition is used to specify the properties of a trigger. Below is

## Trigger Type

- **CALLABLE**: A trigger that has no inbound endpoint of its own the workflow is invoked directly, by another workflow or by a caller that holds a reference to it. `workflow/v1/newWorkflowCall` is the built-in example, and it is also the trigger that makes a workflow exposable as an MCP or A2A tool.
- **CALLABLE**: A trigger that has no inbound endpoint of its own - the workflow is invoked directly, by another workflow or by a caller that holds a reference to it. `workflow/v1/newWorkflowCall` is the built-in example, and it is also the trigger that makes a workflow exposable as an MCP or A2A tool.
- **DYNAMIC_WEBHOOK**: A trigger that listens for incoming HTTP requests at a dynamically generated URL.
- **HYBRID**: Combines features of both polling and webhook triggers. It can listen for events via webhooks and also poll for updates, providing flexibility in handling different event sources.
- **LISTENER**: A trigger that continuously listens for specific events or messages from a source, such as a message queue or event stream, and activates when those events occur.
Expand Down
10 changes: 5 additions & 5 deletions docs/content/docs/developer-guide/generate-component/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: "Scaffold a new component from an OpenAPI specification using the B

## Generate Component [toc]

In the following steps, we will learn how to generate a new component from an OpenAPI specification using the ByteChef CLI (`cli/cli-app`). The CLI reads your API's OpenAPI definition and scaffolds a full component module actions, properties, and a connection so you don't have to write them by hand.
In the following steps, we will learn how to generate a new component from an OpenAPI specification using the ByteChef CLI (`cli/cli-app`). The CLI reads your API's OpenAPI definition and scaffolds a full component module - actions, properties, and a connection - so you don't have to write them by hand.

OpenAPI, formerly known as Swagger, is a specification for building APIs that allows developers to define their API's structure in a standardized format. By using the CLI, you can streamline the process of creating components by automatically generating code based on your OpenAPI definitions.

Expand All @@ -14,22 +14,22 @@ OpenAPI, formerly known as Swagger, is a specification for building APIs that al
<Steps>
<Step>

**[Initial setup](/developer-guide/generate-component/initial-setup)** create the component package and register it in the Gradle build.
**[Initial setup](/developer-guide/generate-component/initial-setup)** - create the component package and register it in the Gradle build.

</Step>
<Step>

**[OpenAPI specification](/developer-guide/generate-component/open-api-specification)** add your `openapi.yaml` and run the CLI `component init` command to generate the component.
**[OpenAPI specification](/developer-guide/generate-component/open-api-specification)** - add your `openapi.yaml` and run the CLI `component init` command to generate the component.

</Step>
<Step>

**[Customize the component](/developer-guide/generate-component/customize-component)** set the icon and category, adjust the connection and actions, and enable dynamic options, dynamic properties, dynamic output, and AI Agent tools via OpenAPI extensions.
**[Customize the component](/developer-guide/generate-component/customize-component)** - set the icon and category, adjust the connection and actions, and enable dynamic options, dynamic properties, dynamic output, and AI Agent tools via OpenAPI extensions.

</Step>
<Step>

**[Create a trigger](/developer-guide/generate-component/create-trigger)** triggers are not generated from OpenAPI, so add them manually and wire them into the generated handler.
**[Create a trigger](/developer-guide/generate-component/create-trigger)** - triggers are not generated from OpenAPI, so add them manually and wire them into the generated handler.

</Step>
</Steps>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ title: "OpenAPI Specification"
| `--base-package-name` | Package for the generated classes. Defaults to `com.bytechef.component`. |
| `--internal-component` | Whether the component ships with the platform. Defaults to `false`; `bytechef.sh` passes `true`. |

If you would rather run the CLI as a standalone binary for a component you keep outside this repository build it once with `./gradlew :cli:cli-app:installDist` and call `cli/cli-app/build/install/bytechef/bin/bytechef`. The binary runs from your current working directory, so paths behave as you expect, and it does **not** pass `--internal-component`.
If you would rather run the CLI as a standalone binary - for a component you keep outside this repository - build it once with `./gradlew :cli:cli-app:installDist` and call `cli/cli-app/build/install/bytechef/bin/bytechef`. The binary runs from your current working directory, so paths behave as you expect, and it does **not** pass `--internal-component`.
10 changes: 5 additions & 5 deletions docs/content/docs/developer-guide/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ The Developer Guide is for engineers who want to extend ByteChef with new **comp

There are two supported paths, and they are complementary:

- **[Build a component by hand](/developer-guide/build-component/initial-setup)** start from the `example` component template and write the definition, actions, triggers, connection, and tests yourself. Best for components with custom logic, non-REST protocols, or bespoke behavior.
- **[Generate a component from OpenAPI](/developer-guide/generate-component)** point the CLI at an OpenAPI specification and let it scaffold the actions, properties, and connection for you, then customize the generated code. Best for REST APIs that already ship an OpenAPI spec.
- **[Build a component by hand](/developer-guide/build-component/initial-setup)** - start from the `example` component template and write the definition, actions, triggers, connection, and tests yourself. Best for components with custom logic, non-REST protocols, or bespoke behavior.
- **[Generate a component from OpenAPI](/developer-guide/generate-component)** - point the CLI at an OpenAPI specification and let it scaffold the actions, properties, and connection for you, then customize the generated code. Best for REST APIs that already ship an OpenAPI spec.

Both paths produce the same artifact: a component module that the platform discovers and surfaces in the workflow editor's component panel.

## Reference

- **[Component specification](/developer-guide/component-specification/component)** every DSL method for the [component](/developer-guide/component-specification/component), [action](/developer-guide/component-specification/action), [trigger](/developer-guide/component-specification/trigger), [connection](/developer-guide/component-specification/connection), and [property](/developer-guide/component-specification/property) builders, method by method.
- **[Working with triggers](/developer-guide/working-with-triggers)** configuring ngrok and the local webhook URL so provider callbacks reach your machine while developing webhook triggers.
- **[Component specification](/developer-guide/component-specification/component)** - every DSL method for the [component](/developer-guide/component-specification/component), [action](/developer-guide/component-specification/action), [trigger](/developer-guide/component-specification/trigger), [connection](/developer-guide/component-specification/connection), and [property](/developer-guide/component-specification/property) builders, method by method.
- **[Working with triggers](/developer-guide/working-with-triggers)** - configuring ngrok and the local webhook URL so provider callbacks reach your machine while developing webhook triggers.

## Understand the internals

- **[Architecture deep dive](/developer-guide/architecture)** how the Atlas engine, message broker, trigger machinery, and Component SDK fit together, and what happens between hitting **Run** and a task's `perform` function executing.
- **[Architecture deep dive](/developer-guide/architecture)** - how the Atlas engine, message broker, trigger machinery, and Component SDK fit together, and what happens between hitting **Run** and a task's `perform` function executing.
Loading
Loading