Please note:this document is a work in progress.

Core Kit

This is the kit that provides the most fundamental building blocks for Breadboard. The component it provides tend to be fairly low-level. Think of these components as indivisible atoms of Breadboard universe, or as the plumbing that makes everything run. Many of the other components (all of the Agent Kit components, for example) are created by wiring using these together.

Tip

Most of these components are closer to actual programming than just dragging and dropping high-level components. Expect climbing a learning curve to get comfortable using them.

The cast component

Takes any kind of value and forces its schema to be the given JSON Schema.

Input ports

The cast component has two input ports:

Output ports

The cast component has a single output port:

Example

In the board above, a URL is fetched which responds with an object containing properties foo and bar. Since the fetch component doesn't intrinsically know what the response type of any given request will be, by default it will be typed as unknown. By wiring the response to a cast node, we can assert to Breadboard what the expected response type is.

Implementation

The curry component

Takes a board and bakes in (or curries, using the computer science term) the supplied port inputs into it. Very useful when we want to invoke a board with the same input values many times (like with map).

Input ports

The curry component has a single input port plus any number of additional ports.

Values supplied with any additional ports will be curried into the output board.

Output ports

The component has a single output port.

Example

Let's suppose that we have this board that creates a simple greeting given a name and location, using the promptTemplate component.

If we need to print out a set of greetings for a bunch of people visiting from the same location, we can use the curry component to bake the Location information into the board and then call it multiple times with a different name.

Tip

The curry component is also useful for introspecting boards: you can use it to load a board via a URL and then examine the output as BGL.

Implementation

The deflate component

This component converts all inline data to stored data, saving memory. Useful when working with multimodal content.

Input ports

The component has a single input port.

Output ports

The component has a single output port.

Example

In the board above, a chunk of JSON is fetched. This JSON contains a base64-encoded string of an image. The deflate component turns it into a lightweight handle and then passes it on to output.

Implementation

The fetch component

Use this component to fetch data from the Internet. Implementation-wise, this is a wrapper around Fetch API with a few Breadboard-specific tweaks.

The tweaks are:

Input ports

The component has the following input ports.

Output ports

Example

In the board above, the fetch component makes a call to Wikipedia open search API and then passes the response to the output.

Implementation

The inflate component

Does opposite of what the deflate component does. Scans provided data and converts all lightweight handles to inline, base64 encoded strings.

Input ports

The component has a single input port.

Output ports

The component has a single output port.

Example

In the board above, any multimedia content supplied as input will be turned into base64-encoded strings.

Implementation

The invoke component

Invokes (using "run as component" runtime mode) specified board, supplying remaining incoming wires as input ports for that board. Returns the outputs of the board as its own output ports.

Use this component to invoke another board from your board.

Input ports

This component has a single static input port and multiple dynamic ports.

Output ports

The output ports of this component are the outputs of the invoked board.

Example

In the board above, the invoke component is used to invoke this board:

Following the semantics of the "run as component" mode, all inputs of the invoked board are populated by the input ports of the invoke component input ports, and all outputs of the invoked board are passed as output ports.

Tip

Note how "Name" and "Location" input ports, as well as the "Greeting" output ports pop up in the Visual Editor when the "Board" input port is populated. This is the key property of the "run as component" mode: the board API is declarative and can be statically described.

Implementation

The map component

Given a list items and a board, runs the board in "run as component" mode for each item in the list. Similar in to JavaScript Array.prototype.map function, except boards run in parallel.

When running the board, the map component will supply three inputs with these ids:

This very is similar to the arguments of the JavaScript Array.prototype.map function.

Input ports

The component has two statically defined input ports:

Output ports

The component has one statically defined output port:

Example

Given this board that creates a simple greeting given a name and location:

We can use the map component to print out a set of greetings for a bunch of people.

Tip

The curry component and map component often go hand in hand, just like in the example above. Currying provides a convenient way to pass unchanging arguments to the board that is being invoked multiple times via map.

Implementation

The passthrough component

This is a no-op component. It takes the input port values and passes them along as output port values, unmodified. Just like any no-op statement in programming, this component comes in handy in various situations, like when the board needs an entry point, but the rest of the board forms a cycle.

Input ports

Output ports

Implementation

The reduce component

Given a list, an initial accumulator value, and a board, invokes a board in "run as component" mode for each item and accumulator in the list, returning the final accumulator value. Loosely, same logic as the Array.prototype.reduce function in JavaScript.

When running the board, the reduce component will supply input values with the following ids:

In the outputs, it will look for the output values with the following ids:

Input ports

The reduce component has three static input ports:

Output ports

The component has one static output port:

Example

Let's suppose we want to research a few topics on Wikipedia, and get a bunch of links for each topic. First, we'll build a board that fits the shape required by the reduce component. This board will query Wikipedia for one topic.

Then, we can use another board that makes it run over a list of topics using the reduce component.

Implementation

The runJavascript component

Use this component to execute JavaScript code. It is particularly useful for manipulating data between other components or adding other kinds of logic to your boards.

Note

The code is executed in a new V8 context in component or a Web Worker in the browser, which means that it cannot access any variables or functions from outside the context in which it is run.

The key input port is Code, which contains the code to execute. The code must be a JS function. When the component is run, the function is called with a single argument, which is an object with each key holding a value of the ports that are wired in:

type PortName = string;
// Each key in this object is an input port name that is wired in,
// and the value is the value that was passed into this port.
type InputValues = Record<PortName, JsonSerializable>;

The name of the function is specified by the Function Name port and is run by default.

Tip

Unless there's a specific need to do so, leave Function Name port value as default.

Depending on the value of the Raw Output port, the return value of the called function is interpreted in two different ways:

function run(inputs: InputValues): JsonSerializable {
  return "This will be a `Result` port value";
}
// Each key is an output port name that is wired out,
// and the value is a JSON-serializable value that is
// passed out of this port.
type OutputValues = Record<PortName, JsonSerializable>;

function run(inputs: InputValues): OutputValues | Promise<OutputValues> {
  return {
    yes: "This will be a value of the `yes` port",
    no: "This will be a value of the `no` port",
  };
}

To aid with specifying the input and output ports, there are two additional configuration ports: Input Schema and Output Schema, respectively.

Input ports

The component has the following static input ports:

The component may have zero or more dynamically wired ports, each passed as part of the function argument.

Output ports

The component has either a single or no static output ports:

When the Raw Output is true, the output ports are all dynamic and are defined as keys of object, returned by the called function.

Example

The board above is a very simple string splitter. The body of the function is:

function run({ topics }) {
  return topics.trim().split("\n");
}

The component uses the default Raw Output = false value, and so the return value of the function becomes the Result port value.

Let's consider a bit more elaborate example. Suppose we want to create a router: a way to choose which path to take within a board. This is a very common pattern in Breadboard, because such routing enables a board to perform different actions depending on the inputs it receives.

In this example, we check to see if the list of topics we supplied has only one item, and if so, we print out an output message stating that. Otherwise, we print the list of topics.

The Raw Output port is set to true and the body of the function is:

function run({ topics }) {
  const list = topics.trim().split("\n");
  if (list.length < 2) {
    return {
      message: "Please supply more than one topic.",
    };
  }
  return { list };
}

Instead of returning just a value, we return an object with ports as keys and port values.

Implementation

The secrets component

Use this component to access sensitive data, such as API keys or other valuable bits of information that you might not want to store in the board. The component takes in an array of strings as input port Keys, looks for these keys in its store and, if found, returns them as outputs.

Note

Different implementations of Breadboard will use their own strategies for retrieving secrets. The Visual Editor opts to ask the user whenever it runs into a need for a secret, and then stores these secrets in browser local storage.

The input ports

The output ports

Example

The board above makes a Gemini API call to list models. To do this, it first retrieves a GEMINI_KEY secret and then uses the fetch component to get the results.

Implementation

The service component

Represents an external service that can be used by the board. Useful for integrating external services with Breadboard.

Input ports

Service inputs

This component a single fixed "Service URL" configuration port, The endpoint at that URL must conform to Breadboard Service Endpoint (BSE) protocol.

Once the "Service URL" port is configured, Breadboard Visual Editor will ask the service to describe itself and use that description to supply additional input and output ports.

In the example above, the "Query" input port and "News" output port is created based on this description.

Note

In addition to Breadboard Service Endpoints being able to describe themselves, they also react to configured and wired inputs, making it possible to write services whose inputs and outputs change based their configuration.

Output ports

The output ports are defined by the Breadboard Service Endpoint.

Example

For a sample implementation of a BSE protocol, see the Google News Service on Valtown, which is used in the board above.

Tip

Valtown is a quick and easy to create HTTP endpoints for Breadboard services.

Implementation

The unnest component

Exposes all properties of a given JSON object as separate output ports.

Input ports

The unnest component has a single input port.

Output ports

The unnest component will create one output port for each property in the given object.

Implementation