Search the complete documentation

Try idempotency, proposal lifecycle, authentication, or ordering.

Navigate Open
繁體中文
Browse documentation

Govern · First reply

Assisted website integration

The website path is an assisted integration reference, not a Govern self-service or SDK quickstart. LINE is an architecturally defined path, not a currently supported product mode with end-to-end Govern verification. Both preserve the same Govern effect contract.

Govern + Relay

One reply, two system owners

Website path

  1. Host UI

    Requests session material from Govern.

  2. Relay

    Joins the channel and sends with a stable nonce.

  3. Govern

    Revalidates context and produces a bounded reply.

  4. Relay

    Assigns sequence and delivers the bot message.

ModeUser surfaceTransport pathCurrent proof
WebsiteProduct-owned web UIGovern session → Relay SDKAssisted reference integration; Govern-to-Relay reply path is tested
LINE BotLINE Official AccountLINE webhook → Relay LINE adapterArchitecturally defined; Relay ingress and egress are tested, but end-to-end Govern verification is not captured

Mode 1: Website reply

The website path starts with a product-owned conversation UI. Tonetify creates a Relay session for a configured bot profile; Relay transports the user message; Govern resolves the runtime context and produces a reply effect; Relay delivers the bot message back to the same channel.

Browser
  → POST /session to Govern
  → connect and send through Relay
  → signed message.created webhook to Govern
  → Govern reply effect
  → bot message through Relay

This composition keeps one owner per problem. Govern does not implement a second chat transport, and Relay does not decide what the bot should say.

Maturity and prerequisites

This is an assisted website integration reference, not a Govern self-service or SDK quickstart. You need:

  • a configured Govern bot profile;
  • a configured Relay provider credential and provider channel;
  • the built @tonetify/relay artifact or your own Relay client;
  • a deployed callback path from Relay message.created events to Govern.

The Relay SDK is published as @tonetify/relay@0.1.0-beta.1. Pin that exact beta version until Relay publishes a server compatibility matrix and upgrade policy.

1. Create a website session

Call Govern with the provider-channel installation ID created for this bot:

const response = await fetch("https://govern.example.com/session", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    provider_channel_id: "govern-provider-channel-id",
    subject: { type: "visitor", id: "visitor-123" },
    actor: { type: "anonymous" }
  })
});

if (!response.ok) throw new Error(`session failed: ${response.status}`);

const { data: session } = await response.json();

The response contains the Relay connection material selected by Govern:

{
  "data": {
    "token": "host-signed-relay-jwt",
    "tenantId": "relay-tenant-id",
    "channelId": "relay-channel-id",
    "userId": "session-user-id",
    "socketUrl": "wss://relay.example.com/socket",
    "apiUrl": "https://relay.example.com",
    "botName": "Operations Assistant",
    "providerChannelId": "govern-provider-channel-id",
    "organizationName": "Example Organization",
    "botProfileId": "govern-profile-id"
  }
}

POST /session creates transport state. It does not return a model response or execute a Govern turn.

2. Connect to Relay and send

import { ChatClient } from "@tonetify/relay";

const client = new ChatClient({
  url: session.socketUrl,
  apiUrl: session.apiUrl,
  token: session.token,
  userId: session.userId
});

client.connect();

const channel = client.channel(session.channelId, session.tenantId);

channel.on("msg:new", (message) => {
  console.log(message.seq, message.body);
});

await channel.join();
await channel.send("What can you help me with?", {
  nonce: crypto.randomUUID()
});

The user message and the bot reply both arrive as Relay msg:new events. Use Relay’s server-assigned seq to render them in order.

3. Understand the Govern turn

Relay signs and delivers message.created to Govern. Govern then:

  1. verifies the webhook and claims its idempotency identity;
  2. resolves the organization, bot profile, and runtime mode from the provider channel;
  3. appends the input to its conversation state;
  4. runs InputEnvelope → TurnOrchestrator;
  5. dispatches the resulting reply through the provider adapter;
  6. records runtime trace metadata.

A static-profile bot can answer from configured rules and knowledge. A tool-agent bot may call a pinned Host Tool before deciding whether to return reply, proposal, or noop.

Mode 2: LINE Bot reply

LINE uses Relay’s in-tree LINE adapter. Govern still sees a signed Relay message.created event and returns its effect through the same Relay message write path.

LINE user message
  → POST /adapters/line/webhook to Relay
  → X-Line-Signature verification
  → tenant route and per-user LINE channel
  → Relay message.created webhook to Govern
  → Govern reply effect through Relay
  → LINE reply_token when fresh, otherwise push

Relay owns the provider-specific work:

  • verifies the exact raw body with X-Line-Signature;
  • routes LINE destination to one tenant;
  • creates or reuses one LINE channel per external user;
  • stores the inbound reply_token with a bounded validity window;
  • sends the reply through the normal Relay message path;
  • consumes a fresh reply token once, then falls back to LINE push when no usable token remains.

Govern remains provider-neutral. It receives provider: "relay", the Relay tenant ID, channel ID, message ID, and body. It resolves those fields to a configured bot profile before running the same InputEnvelope → TurnOrchestrator → EffectDispatcher path used by website chat.

Current integration boundary

The LINE transport itself has repository-level end-to-end coverage in Relay. The cross-repo dynamic mapping is not yet productized: Relay creates LINE user channels on demand, while Govern currently fails closed unless the exact Relay tenant and channel already have a ProviderChannel mapping.

Therefore LINE Bot reply is an architecturally defined path, not a currently supported product mode with end-to-end Govern verification. The missing close is automatic or deterministic provider-channel registration plus one captured LINE → Govern → LINE bot-reply proof.

Failure behavior

ConditionResult
Provider channel, organization, profile, or credential is unknown404 RFC 9457 problem detail
Provider is not the current Relay adapter, identified as relay422 unsupported_provider
Relay configuration is incomplete422 missing_relay_config
Relay session creation fails upstream502 upstream_session_failed
Message retry uses a new nonceRelay treats it as a new logical message
LINE signature or destination is invalidRelay rejects or ignores the provider webhook before Govern runs
LINE channel has no Govern provider mappingGovern fails closed with runtime_context_not_found; no bot reply is produced
LINE reply token is expired or consumedRelay attempts LINE push instead of reusing the token
Runtime cannot produce a replyThe turn records an error; Govern must not invent host truth

Ownership boundary

  • The browser owns presentation and session lifecycle.
  • LINE owns its user identity, webhook event, reply token, and Messaging API contract.
  • Relay owns provider ingress, channel, membership, message order, retry-safe send, and delivery.
  • Govern owns runtime context resolution and the bounded reply, proposal, or noop result.
  • The host owns identity, business truth, policy, and execution.

Next: learn how Govern chooses an effect.