Skip to main content
Cross-platform sessions let one user keep a single conversation across every messaging platform.
The user continues the same conversation on Telegram, then Discord; identity linking mirrors session history across platforms.

How It Works

Quick Start

1

One platform, one user

2

Two platforms, one user (recommended)

3

In-process testing / ephemeral


Choosing Your Resolver


StoreBackedIdentityResolver

StoreBackedIdentityResolver extends the core FileIdentityResolver with a read-through to the gateway pairing store, so users who have already paired share a session out of the box. Resolution order:
  1. Explicit link registered via link() (highest priority)
  2. Pairing-store label for (user_id, platform) when the channel is paired and carries a non-empty label
  3. f"{platform}:{user_id}" — safe per-platform fallback (no merging)
Useful when the pairing store is volatile or about to be rotated — this pins the canonical-id mapping into the resolver’s own JSON file.
If you already use praisonai pairing approve <platform> <code> --label <canonical>, switching to StoreBackedIdentityResolver.from_env() is a one-line upgrade: paired users immediately share one session across all their channels, with no separate praisonai identity link calls required. Run praisonai identity import once to pin those mappings into the explicit link map.

In the gateway (praisonai gateway start)

The flagship WebSocketGateway daemon accepts the same resolver, so a paired user keeps one continuous session across every channel served by one gateway process. Wire it three ways — YAML block, CLI flag, or Python override.

Precedence

WebSocketGateway(identity_resolver=…) > --identity-store > identity: YAML block > default (per-platform keys) An explicit constructor or CLI resolver is never clobbered by the YAML block, even on hot-reload. The gateway stamps the resolver onto each channel bot’s session manager at startup and on every hot-reload:
Gateway process: In the praisonai gateway start daemon, the resolver is stamped onto each channel bot’s session manager via WebSocketGateway._stamp_identity_resolver() (mirrors _stamp_admission_gate). Restarted channels during hot-reload keep the resolver too — see Gateway Config Reload.

End-to-end: one session across two platforms

  1. Operator approves both channels for the same label:
  2. Operator adds identity: { enabled: true } to gateway.yaml (or passes --identity-store).
  3. Alice on Telegram: "my favourite colour is octarine".
  4. Hours later, Alice on Discord: "what's my favourite colour?".
  5. The gateway resolves both to alice, loads the same session history, and replies "Octarine.".

CLI: praisonai identity

Four subcommands manage identity links from the command line. Each subcommand accepts:

SessionContext for Tools

Any tool the agent calls can read who is messaging:

SessionContext Fields

Use set_session_context / clear_session_context for advanced custom adapters. Returns a token; reset in a finally block.

Concurrent Turns Across Adapters

With an identity resolver configured, near-simultaneous turns from different adapters that resolve to the same unified user run one at a time against that user’s single transcript. Each adapter — Telegram, Discord, Slack — keeps its own session manager, and the identity resolver unifies them onto one persisted session per human. Before this fix, each adapter still guarded its turns separately, so two adapters could run turns for the same human at the same time and scramble the order of their shared transcript.

When it matters

  • A cron or scheduled outbound delivery lands on platform A while the user replies on platform B — the mirror and the inbound reply serialise cleanly (see Mirror for Outbound Deliveries).
  • A user types on Telegram while their smartwatch fires a Slack message in the same second — the second turn waits for the first to commit before appending, so the transcript stays in strict user → assistant → user order.
Nothing to configure. This is automatic whenever an identity resolver is wired via BotOS(identity_resolver=…), the gateway’s identity: YAML block, or --identity-store. Deployments without a resolver are unchanged.
Multi-replica gateways: the shared turn lock stamped onto channel bots is in-process only. If you scale the gateway to replicas > 1, enable a distributed backend — see Gateway Turn Lock.

Mirror for Outbound Deliveries

Cron jobs, scheduled deliveries, and cross-platform replies need to mirror the assistant’s outbound message into the user’s history:

Parameters

Errors are swallowed and logged — a mirror failure must never break the outbound delivery itself.

Storage & Privacy

FileIdentityResolver defaults to ~/.praisonai/identity.json (override via PRAISONAI_IDENTITY_PATH env var or constructor path=). File is written atomically and chmod 0o600.
Identity links are explicit and opt-in. No automatic linking — wire the resolver only after a verified DM-pairing flow confirms the same human controls both accounts.
Without a resolver, the legacy bot_{platform}_{user_id} storage key is preserved bit-for-bit — fully backward compatible.
Running the flagship daemon? See In the gateway (praisonai gateway start) for wiring the same resolver via the identity: YAML block, --identity-store, or the WebSocketGateway constructor.

Best Practices

For production wrapper deployments, use StoreBackedIdentityResolver.from_env() — it picks up paired channels automatically and falls back to the same safe platform:user_id default. Plain FileIdentityResolver is the right choice only when you do not use the pairing system.
For multi-process/multi-host deployments, back it with SQLite, Redis, or a database:
Never auto-link based on display name. Always require a DM-verified pairing flow:
Instead of os.environ, read SessionContext — concurrent message handlers won’t trample each other:

BotOS

Multi-platform bot orchestrator

Messaging Bots

Platform-specific bot guides

Bot Pairing

Secure unknown-user onboarding

Unknown-User Pairing

Inline-button approval for bots

Gateway CLI

--identity-store and other gateway start flags

Gateway Config Reload

Hot-reload the identity: block without dropping turns