# Synergies API — Find related entities (https://brainapi.lumen-labs.ai/docs/v2/retrieval/entities/synergies)

> For the complete BrainAPI documentation index, see [llms.txt](https://brainapi.lumen-labs.ai/docs/llms.txt). A markdown version of any docs page is available by appending `.md` to its URL (e.g. https://brainapi.lumen-labs.ai/docs/v2/retrieval/entities/synergies.md).

Find graph peers connected to a target through shared anchors and event relationships

Use `GET /retrieve/entity/synergies` to find entities related to a target through the graph. The endpoint resolves a target, explores direct and event-mediated anchors, scores eligible peer nodes, and returns the strongest associations.

This is useful beyond ecommerce. Examples include services connected to the same incident, courses related through shared skills, researchers connected through projects, or controls connected through the same policy requirement.

## Mental model

Suppose two `SERVICE` nodes participate in the same incident event. The incident can act as an anchor connecting them. The response returns each peer as `node`, the anchors that explain the association in `connected_by`, and an `association_score` for ordering.

The endpoint is still graph retrieval:

- It needs useful nodes and relationships.
- It returns entities, not passages.
- It can use same or opposite node polarity.
- It is not the same as query search or the multi-channel recommendation endpoint.

### Event hubs connect peers

In the diagram below, Maria initiates an employment event that targets Tom and Lisa. The event hub preserves the action as a first-class node. Because Tom and Lisa participate in the same event structure, the graph has an explainable path for treating them as related peers.

![Maria initiates an employment event whose targets are Tom and Lisa](/images/positive-polarity-example-maria.png)

The same pattern can represent services participating in an incident, researchers contributing to a project, or courses addressing a shared skill. The domain changes; the shared-anchor principle does not.

## Find services related to an incident participant

```bash
curl --get "http://localhost:8000/retrieve/entity/synergies" \
  -H "BrainPAT: $BRAINPAT_TOKEN" \
  -H "X-Brain-ID: operations" \
  --data-urlencode "target=payments-api" \
  --data-urlencode "polarity=same" \
  --data-urlencode "labels=SERVICE" \
  --data-urlencode "top_k=10" \
  --data-urlencode "ppa=true"
```

A shortened response looks like:

```json
{
  "target_node": {
    "uuid": "service-42",
    "labels": ["SERVICE"],
    "name": "payments-api"
  },
  "synergies": [
    {
      "node": {
        "uuid": "service-77",
        "labels": ["SERVICE"],
        "name": "checkout-api"
      },
      "connected_by": [
        {
          "uuid": "incident-19",
          "labels": ["EVENT"],
          "name": "Connection pool saturation"
        }
      ],
      "association_score": 0.0
    }
  ],
  "anchors": []
}
```

The numeric value above demonstrates the response type only; it is not a quality claim or expected score. Interpret rankings within one result set and evaluate them against your graph and task.

## Request controls

| Parameter | Default | Meaning |
| --- | --- | --- |
| `target` | Required | Name or description used to resolve the starting node. |
| `polarity` | `same` | `same` keeps matching polarities. `opposite` keeps positive↔negative pairs and excludes neutral or missing polarity. |
| `do` | `false` | When `true`, restricts results to direct synergies. |
| `pa` | `false` | Include `potential_anchors` in the response when available. |
| `ppa` | `false` | Include seed `anchors` in the response when available. |
| `top_k` | `50` | Maximum number of synergies returned. |
| `labels` | None | Repeated candidate-label filter; a candidate must intersect it. |

`labels` is serialized as repeated query parameters, for example `labels=COURSE&labels=WORKSHOP`.

## Visual guide to traversal controls

The controls change which graph evidence is returned or allowed to contribute. They do not turn the endpoint into passage search.

### Direct-only results with `do=true`

Direct-only mode restricts discovery to direct synergy structure. In this example, Maria has direct graph branches through the `Owns` and `Graduated` hubs; James and Michael are found through those directly shared structures.

![Direct synergy paths through shared Owns and Graduated hubs](/images/example-do.png)

Use direct-only mode when indirect event or similarity expansion creates too many weak peers. Avoid it when multi-step event structure carries important evidence.

### Seed anchors with `ppa=true`

Seed anchors are the graph nodes reached from the target and used to discover peers. Requesting `ppa=true` includes them in the response as `anchors`, making the association easier to inspect.

![Maria connected to seed anchors for Stanford, Cafe Shop, Lisa, and Tom](/images/example-pa.png)

### Potential anchors with `pa=true`

Potential anchors are similar nodes that could explain or extend an association but are not necessarily connected through the same direct path. Requesting `pa=true` includes them as `potential_anchors` when available.

![Potentially similar anchors such as Stanford and UC Berkeley or Cafe Shop and Pastry Shop](/images/example-ppa.png)

Potential anchors are diagnostic evidence, not automatically accepted relationships. Inspect them before changing the graph or using them as application truth.

## How the association score is calculated

`association_score` is a ranking signal built from embedding similarity and graph-path evidence. It is not a probability, confidence percentage, or globally calibrated value. Compare scores within one request and one configuration.

The implementation is in [`entity_sibilings.py`](https://github.com/Lumen-Labs/brainapi2/blob/main/src/core/search/entity_sibilings.py), with similarity helpers in [`numbers.py`](https://github.com/Lumen-Labs/brainapi2/blob/main/src/utils/similarity/numbers.py).

### 1. Cosine similarity

BrainAPI compares available node, relationship, and event-context embeddings with cosine similarity:

```math
\operatorname{cosine}(a,b)
=
\frac{a \cdot b}{\lVert a \rVert\,\lVert b \rVert}
```

A value closer to `1` means the vectors point in a similar direction. A zero-length vector produces `0` in the shipped helper. Cosine similarity alone does not prove that two entities have a valid graph relationship; it supplies one component of the path score.

### 2. Weighted similarity

For event-mediated candidates, BrainAPI strengthens the node-to-target description component with `wsim`:

```math
\operatorname{wsim}(s,w)=s^{1-w}
```

The shipped node-description weight is:

```math
w_d = 0.5
```

Therefore that branch uses the square root of the node similarity:

```math
t=\operatorname{wsim}\!\left(\operatorname{cosine}(v_n,v_t),0.5\right)
```

This transformation assumes a non-negative similarity input. It raises smaller positive similarities while preserving `0` and `1`; it should not be interpreted as learned calibration.

### 3. Relationship and event-context similarity

For an event-mediated path, the candidate-side context combines the relevant event-edge embeddings, then compares that representation with the target-side context:

```math
r=
\operatorname{cosine}\!\left(
\frac{v_{e,c}+v_{r,c}}{2},
v_{ctx,t}
\right)
```

Here, `v_{e,c}` and `v_{r,c}` represent the candidate-side event and relationship evidence, while `v_{ctx,t}` represents the relationship context collected from the target side. Direct paths use the available direct-relationship embedding evidence instead of an event-context mean.

### 4. Per-path association score

When both the target-side similarity component `t` and relationship/context component `r` are non-zero, BrainAPI calculates:

```math
A_{path}=m\cdot\frac{t+r}{2}
```

The multiplier favors graph evidence reached through a direct seed over evidence reached through a similar, remote seed:

```math
m=
\begin{cases}
1.30 & \text{direct seed} \\
0.70 & \text{remote similar seed}
\end{cases}
```

If either required component is missing or zero, the shipped implementation assigns that path a score of `0`. Because the direct multiplier is greater than one, an association score can exceed `1`; this is another reason not to treat it as a probability.

For intuition only, if `t=0.64` and `r=0.48`, the mean component is `0.56`. The same evidence would contribute `0.728` through a direct seed and `0.392` through a remote seed. These numbers demonstrate the formula; they are not expected production scores.

### 5. Merge evidence from multiple anchors

When another seed connects to a candidate already found, BrainAPI merges the previous association score `p` and new path score `n` with `wmean` and `FACTORS_INCREMENTAL_WEIGHT=0.3`:

```math
A_{merged}=\operatorname{wmean}([p,n],0.3)
```

The general helper defines:

```math
w_{eff}(N)=w\cdot\frac{\max(1,N-2)}{\max(2,N)}
```

and transforms its first two inputs before taking the mean:

```math
\operatorname{wmean}(\{x_i\},w)
=
\frac{
x_1^{1-w_{eff}(N)}+x_2^{1-w_{eff}(N)}+\sum_{i=3}^{N}x_i
}{N}
```

The Synergies merge passes two values, so `w_eff=0.15` and the two exponents are `0.85`. This rewards a candidate supported through more than one useful anchor without simply summing scores.

### Scoring constants and limits

| Constant | Shipped value | Effect |
| --- | --- | --- |
| `DIRECT_MULTIPLIER` | `1.30` | Boosts evidence reached through a direct seed. |
| `REMOTE_MULTIPLIER` | `0.70` | Discounts evidence reached through a similar remote seed. |
| `NODE_SIM_DESC_INCREMENTAL_WEIGHT` | `0.50` | Applies the weighted-similarity transform to event-mediated node similarity. |
| `FACTORS_INCREMENTAL_WEIGHT` | `0.30` | Controls the incremental merge of multiple anchor paths. |

Before scoring, BrainAPI excludes deprecated or invalidated predicates and applies candidate label and polarity constraints. It sorts the remaining candidates by descending `association_score`, then truncates to `top_k`. A strong score cannot rescue a candidate rejected by those eligibility rules.

## Same and opposite polarity

Use `same` when peers should express compatible orientation: two helpful courses, two preferred media items, or two services affected in the same way. Nodes with neutral or missing polarity are compatible with each other in this mode.

Use `opposite` only when the graph deliberately models positive and negative sides of a need. A negative problem node might connect to a positive remediation node. Neutral or missing polarity never qualifies for `opposite`.

Do not introduce polarity merely to make this endpoint return results. If your domain is not naturally polar, use `same` and model meaningful anchors and labels.

## Decide between related surfaces

| Surface | Choose it when |
| --- | --- |
| Synergies | You want peer entities explained by shared direct or event anchors. |
| [Recommendations](https://brainapi.lumen-labs.ai/docs/v2/retrieval/recommendations) | You need ranked next-item behavior with asymmetric, multi-interest, recency, seen-item, or diversity controls. |
| [Search](https://brainapi.lumen-labs.ai/docs/v2/retrieval/search) | The input is a query and the output should be ranked passages or graph-channel hits. |
| Entity neighbors | You know the entity and want its immediate graph neighborhood rather than peer inference. |
| [MCP](https://brainapi.lumen-labs.ai/docs/v2/agentic/MCP) | The question requires several lookups, changing hypotheses, or evidence synthesis. |

## Evaluate before relying on it

Create a small set of targets with expected peers and explanations. Measure whether the relevant peer appears in the first `k`, then inspect `connected_by` for spurious high-degree anchors. Compare `do=true` with the default path to learn whether indirect event structure contributes signal or noise.

Stop using a channel or anchor type when it repeatedly produces unrelated peers and cannot be corrected through cleaner labels, relationships, or ingestion. A higher graph score is not evidence of business usefulness by itself.

## Troubleshoot

| Symptom | Likely cause | Diagnostic and fix |
| --- | --- | --- |
| `404 No entity found matching the target` | Target resolution failed in the selected brain. | [Check the entity](https://brainapi.lumen-labs.ai/docs/v2/retrieval/entities/existence), confirm the brain, and use a less ambiguous target. |
| Empty `synergies` | No eligible peers share supported graph structure, polarity, or labels. | Remove a label filter temporarily, inspect anchors, and verify relationship embeddings exist. |
| Irrelevant peers | A broad or high-degree anchor dominates. | Inspect `anchors`/`potential_anchors`, tighten labels, or compare direct-only mode. |
| Expected opposite result is absent | One side is neutral, missing, or has the wrong polarity. | Inspect both nodes; opposite matching is strictly positive↔negative. |

For exact schemas and generated request examples, open the [Retrieve API reference](https://brainapi.lumen-labs.ai/docs/v2/reference/api/retrieve).
