Core Concepts
The Bridge is a declarative dataflow language. You do not write scripts or sequential instructions; you wire data sources together to form a circuit.
You describe what data goes where. The Bridge engine figures out when and how to fetch it.
The Mental Model
Section titled “The Mental Model”To master The Bridge, you must stop thinking in line-by-line scripts and start thinking in graphs.
1. Nodes, Not Functions
Section titled “1. Nodes, Not Functions”In traditional languages, you call functions: getWeather("London") and getWeather("Paris").
In The Bridge, you are wiring physical nodes. If you want to use the same tool twice with different parameters, you cannot wire two different cities into the same tool handle—that creates a data conflict. Instead, you instantiate two separate nodes by bringing the tool into scope twice:
# Instantiate two separate nodes in the graphwith hereGeo as geo1with hereGeo as geo2
# Wire them independentlygeo1.q <- i.cityOnegeo2.q <- i.cityTwo2. Lazy, Pull-Based Execution
Section titled “2. Lazy, Pull-Based Execution”The engine is strictly demand-driven. When an incoming GraphQL query asks for a field, the engine traces backward through your wires to find the source.
If a client’s query does not ask for a specific field, the wire connected to it is “dead”—no code runs, and no external APIs are called.
3. Automatic Concurrency
Section titled “3. Automatic Concurrency”Because The Bridge knows the exact shape of your data dependencies, it handles all parallelization automatically:
- Independent targets run concurrently: Because
geo1andgeo2above are independent nodes, the engine fires both HTTP requests in parallel! - Tool inputs run concurrently: If a tool requires three different dynamic parameters, all three are resolved in parallel before the tool is invoked.
- Fallbacks & Logic short-circuit: If you chain sources together (
a || b), or evaluate boolean logic (a and b), the engine evaluates them strictly left-to-right, short-circuiting network requests the moment a definitive answer is found to save execution costs.
4. Per-Request Caching (No N+1)
Section titled “4. Per-Request Caching (No N+1)”When multiple wires read from the same node, the engine only executes that node once per GraphQL operation. The result is cached in memory for the lifecycle of the request, eliminating N+1 bugs entirely.
File Structure
Section titled “File Structure”A .bridge file is a collection of static definitions. Because the execution is demand-driven, the order of blocks in the file does not matter. Every file must begin with a version declaration, followed by any number of const, tool, define, and bridge blocks. Blocks are separated by blank lines, and comments start with #.
version 1.5
# 1. CONST: Shared static dataconst defaultCurrency = "EUR"
# 2. TOOL: Configured API clients or functionstool hereGeo from std.httpCall { .baseUrl = "https://geocode.search.hereapi.com/v1" .method = "GET" .path = "/geocode"}
# 3. BRIDGE: The routing logic for a specific GraphQL fieldbridge Query.getWeather { # Bring dependencies into scope with hereGeo as geo with input as i with output as o
# Wire inputs to the tool geo.q <- i.cityName
# Wire the tool's output to the GraphQL response o.lat <- geo.items[0].position.lat o.lon <- geo.items[0].position.lng}Scopes & Shadow Trees
Section titled “Scopes & Shadow Trees”The Bridge uses strict scoping. You cannot reference a tool, variable, or constant unless you explicitly bring it into the block’s scope using the with keyword.
When you iterate over lists of data (like mapping an array of search results), the engine creates isolated Shadow Scopes (or shadow trees) for each element. This means variables defined inside an array loop remain safely contained within that specific item’s execution context, allowing you to nest data transformations infinitely deep without namespace collisions.