# Third-party Bridges

## Stability

Supported Extension API Level: Advanced

## Goal

Connect external systems to Flow Core through stable data, event, and graph-selection boundaries instead of depending on runtime internals.

## When To Use This

Use a bridge when another package owns information or events that Flow Core graphs should react to. Common examples include inventory plugins, dialogue tools, analytics SDKs, custom input layers, networking systems, quest systems, or procedural content loaders.

The bridge should translate external state into Flow Core concepts:

| Bridge type            | External system owns                                                                | Flow Core receives                                                |
| ---------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| Data bridge            | Current state such as health, quest phase, selected item, or target id.             | Typed Blackboard keys.                                            |
| Event bridge           | A callback such as quest started, level loaded, UI confirmed, or ability requested. | `FlowEventBus` signal or graph Trigger.                           |
| Graph-selection bridge | Which graph variant should run for this object or mode.                             | A `FlowGraphAssetBase` wrapper that creates the selected runtime. |

## Integration Rules

* Keep one source of truth for each value. If the plugin owns health, mirror it into Blackboard; do not let two systems write the same key in the same frame.
* Initialize bridges before the `FlowCoreProcess` needs the data. For scene-owned data, this usually means binding references before the process builds or before the first relevant Trigger fires.
* Publish Flow Core events from the Unity main thread.
* Do not mutate `FlowGraphAsset` structure at runtime. Select a graph through a wrapper instead.
* Avoid reflection, allocation-heavy conversion, and string parsing inside per-frame bridge loops.
* If a callback may unregister signals, destroy objects, or rebuild a process while a signal is being published, defer cleanup by one frame.

## Pattern 1: Data Bridge

Use a data bridge when graphs need to read external state through normal Flow Core value sources.

```csharp
using UnityEngine;
using TwoCatsCode.FlowCore;

public sealed class HealthBlackboardBridge : MonoBehaviour
{
    private static readonly BlackboardKey HealthKey = new BlackboardKey("Health");

    [SerializeField] private Blackboard blackboard;
    [SerializeField] private ExternalHealthSource source;

    private void Update()
    {
        if (blackboard == null || source == null)
            return;

        blackboard.Set(HealthKey, source.CurrentHealth);
    }
}
```

Authoring checklist:

* Create the Blackboard key with the same type the graph expects.
* Add the Blackboard to the process `Local Blackboards` list if the graph reads Local data.
* Write only when the external value changes, or keep the per-frame write small and allocation-free.
* Use Debug Context and Blackboard UI to verify the live value.

Common mistake: writing a string or object value into a key that the graph reads as a number, enum, or reference wrapper.

## Pattern 2: Event Bridge

Use an event bridge when an external callback should start a graph chain.

```csharp
using TwoCatsCode.FlowCore;

public sealed class QuestEventBridge
{
    private static readonly FlowEventKey QuestStarted = new FlowEventKey("Quest.Started");

    public void Bind()
    {
        ExternalQuestSystem.QuestStarted += HandleQuestStarted;
    }

    public void Unbind()
    {
        ExternalQuestSystem.QuestStarted -= HandleQuestStarted;
    }

    private void HandleQuestStarted(int questId)
    {
        FlowEventBus.Global.Publish(
            QuestStarted,
            new FlowTriggerPayload(questId),
            FlowSignalContext.None);
    }
}
```

Authoring checklist:

* Add a Trigger node that listens to the same event key.
* Match the payload type used by the graph.
* Publish from the main thread. If the plugin invokes callbacks on a worker thread, marshal back to Unity first.
* Unbind plugin callbacks when the bridge is disabled or disposed.

Use global events for broad application-level signals. Use local events when a signal targets one process or object identity.

## Pattern 3: Deferred Cleanup

Use deferred cleanup when an event callback may remove listeners or destroy objects while Flow Core is publishing to them.

```csharp
using System.Collections;
using UnityEngine;
using TwoCatsCode.FlowCore;

public sealed class SignalCleanup : MonoBehaviour
{
    private static readonly FlowEventKey CloseKey = new FlowEventKey("UI.Close");
    private FlowTriggerHandle handle;

    private IEnumerator DeferCleanup()
    {
        yield return null;
        FlowEventBus.Global.Unregister(CloseKey, handle);
        Destroy(gameObject);
    }
}
```

The one-frame delay keeps the signal dispatch path simple and avoids modifying listener ownership during the same callback pass.

## Pattern 4: Graph-selection Bridge

Use a graph-selection bridge when the external system chooses which graph a process should run. Implement this as a [Graph Asset Wrapper](/flow-core-docs/documentation/api-extension-guide/graph-asset-wrapper.md), not as runtime graph mutation.

Good uses:

* Loadout chooses a combat graph variant.
* Platform chooses input-specific graph behavior.
* Game mode chooses a rules graph.
* DLC or content pack chooses a graph asset after validation.

Verification is the same as any wrapper: assign it to `FlowCoreProcess`, bind Blackboard data, add a visible Trigger result to each candidate graph, and confirm the selected graph runs in Play Mode.

## Performance Checks

* Profile bridge code in the same scene where graphs run.
* Watch GC allocation for per-frame data bridges.
* Cache keys and external references instead of rebuilding them every frame.
* Keep payload objects direct and short-lived.
* Avoid writing the same Blackboard value every frame if the external source rarely changes.
* Confirm event bridges do not create loops, such as plugin event to Flow Core to plugin event again.

## Failure Modes

| Symptom                                | Likely cause                                             | Fix                                                            |
| -------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------------- |
| Graph reads old data.                  | Bridge writes after the graph Trigger has already fired. | Initialize earlier or fire the Trigger after the data sync.    |
| Graph never reacts to plugin callback. | Event key, Trigger type, or payload type does not match. | Verify the Trigger node and bridge key together.               |
| Works in Editor, fails in build.       | Plugin assembly or define is missing.                    | Guard bridge code with asmdef defines and test a build target. |
| Frame spikes appear after integration. | Bridge allocates or reflects in Update.                  | Cache keys, references, and conversion results.                |
| Signals repeat forever.                | Bidirectional sync creates an event loop.                | Choose one owner and add explicit loop guards.                 |

## Related

* [Extension Points](/flow-core-docs/documentation/api-extension-guide/extension-points.md)
* [Graph Asset Wrapper](/flow-core-docs/documentation/api-extension-guide/graph-asset-wrapper.md)
* [Persistence](/flow-core-docs/documentation/api-extension-guide/persistence.md)
* [Runtime Cost Monitoring](/flow-core-docs/documentation/troubleshooting/runtime-cost-monitoring.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://flow-core.gitbook.io/flow-core-docs/documentation/api-extension-guide/third-party-bridges.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
