Skip to content

Membrane visibility routing

Membrane routing is an alpha interface for controlling who may read and emit ordinary generated tokens. “Membrane” is a routing metaphor: it is not Half, encryption, a security boundary, or a hidden latent chain-of-thought channel.

assistant_public tokens remain in model context and may be emitted. assistant_inner tokens also remain ordinary context tokens, but are removed from user-facing emission and can be hidden from non-assistant viewers by an explicit visibility matrix.

import torch
from arti import (
MEMBRANE_STREAM_ASSISTANT_INNER,
MEMBRANE_STREAM_ASSISTANT_PUBLIC,
MembraneRoutingConfig,
MembraneVisibilityRouter,
build_membrane_visibility,
membrane_emit_tokens,
)
ASSISTANT, USER = 0, 1
router = MembraneVisibilityRouter(MembraneRoutingConfig(hidden_dim=8))
hidden = torch.randn(1, 3, 8) # [B, T, D]
targets = torch.tensor([[0, 1, 0]]) # [B, T], supervised routes
routed = router(hidden, stream_ids=targets)
assert routed.stream_logits.shape == (1, 3, 2)
token_ids = torch.tensor([[101, 202, 303]]) # [B, T]
assert membrane_emit_tokens(token_ids, routed.stream_ids) == [[101, 303]]
readable_by = torch.zeros(2, 2, dtype=torch.bool) # [participant, stream]
readable_by[:, MEMBRANE_STREAM_ASSISTANT_PUBLIC] = True
readable_by[ASSISTANT, MEMBRANE_STREAM_ASSISTANT_INNER] = True
visibility = build_membrane_visibility(
routed.stream_ids, torch.tensor([USER]), readable_by
)
assert visibility.shape == (1, 3, 3) # [B, query, source]

When stream_ids is supplied, the router uses those routes for supervised or curriculum training. When omitted, it chooses argmax over its learned two-way logits. The router does not generate token IDs.

hidden [B,T,D] → Linear(D,2) → stream logits/probabilities [B,T,2]
↓ route IDs [B,T]
token IDs [B,T] ─────────→ public emission mask [B,T]
route IDs + viewer policy ─→ visibility [B,T,T]

membrane_emit_tokens filters the public decode result; it does not delete inner tokens from model context. append_membrane_tokens appends token IDs together with stream metadata and, when supplied, participant and phase IDs. Pass the visibility returned above to an ARTI layer to enforce the read contract.

Treat the runtime as four independent planes:

Plane Input → output Responsibility
Router hidden → stream logits / IDs Learned public-vs-inner assignment
Visibility viewer + stream policy → [B,T,T] Which sources each query may read
Model context token + stream metadata → next context Retain both configured streams
User emit token IDs + stream IDs → public IDs Filter the external decode result

Collapsing model-context append and user emission into one filter would delete the inner feedback path. Conversely, keeping a token in model context does not authorize emitting it.

During training, provide target stream_ids and optimize the two-way stream_logits alongside the normal token objective. During inference, omit stream_ids so the trained router selects a stream; append all generated tokens to model-side context, then emit only the configured public streams. The API supplies this routing contract, but it does not mean an untrained base model already knows when an inner stream is useful.

  • The API enforces tensor routing invariants; it does not prove a language model has learned when to use inner speech.
  • Hidden tokens are not secret against code with access to model memory, tensors, logs, or checkpoints.
  • Applications must keep user emission filtering and model-context updates separate.
  • This surface remains alpha in ARTI 1.7.0; validate it on the target model and task.