NOIR
Capabilities

Conversation control

Control rapid input, groups, contacts, shared-line safety, opt-out, escalation, and channel-safe output.

Conversation capabilities sit between verified channel events and user-visible delivery. They should make behavior more deterministic without guessing identity from display names or message text.

Steering rapid messages

Use @noir-agent/agent/steering to debounce arrivals and choose what a new message does to in-flight work.

StrategyBehavior
appendattach the message to the active generation
queuecreate the next generation after the current one
interruptcancel the active generation and replace it

steeringCapability() adds the runtime behavior. steeredChannel() wraps a channel. Memory and Postgres stores persist batches, claims, generations, and delivery guards. canDeliver() is authoritative: superseded work cannot send a final reply.

Group conversations

@noir-agent/agent/groups adds mention policy and bounded observation context. Unaddressed group messages may be remembered as context without starting the agent. Configure whether state is shared across the group or scoped per participating user.

Group identity must come from stable channel installation and conversation IDs. Never use a mutable channel name as the storage key.

Contacts

@noir-agent/agent/contacts canonicalizes email, phone, Slack, Telegram, WhatsApp, Linq, and Photon identities before exact-owner lookup. Display names and labels remain metadata, not identity.

Use contacts to resolve a destination the user is authorized to reach. Do not let a model-supplied address bypass account ownership or channel policy.

Shared-line safety and suppression

Use @noir-agent/agent/line-safety before sending from a shared phone or messaging identity. It enforces inbound-first rules, suppression, outbound rate windows, new-conversation limits, and unanswered-window limits before atomically reserving a send.

A provider send becomes committed only after the settlement hook records its receipt. A replay returns that receipt rather than sending twice. Expired reservations may be reclaimed only with the current fencing token.

@noir-agent/agent/suppression stores exact-scope opt-out decisions and an audit trail. isOptOutMessage() is a conservative helper, not a substitute for provider compliance events or application policy.

Human escalation

@noir-agent/agent/escalation routes a durable escalation to one or more configured destinations. first-success completes after one route succeeds; all requires every route. Route claims, receipts, and failures are persisted independently so a retry does not duplicate a successful notification.

Escalation is not the same as approval. Approval pauses a specific effect for an authorized decision. Escalation asks a human system or team to take over or respond.

Output formatting

@noir-agent/agent/output-formatting contains deterministic helpers for Slack and plain-text messaging. It normalizes Slack markdown, splits bounded replies without breaking fences, creates fallback text, removes model control leakage, and limits SMS-style bubble counts.

Formatting runs after policy and before channel delivery. It cannot claim a message was sent.

  1. verify and normalize the inbound channel event
  2. apply steering and group policy
  3. resolve exact owner and contacts
  4. run the agent under current generation and cancellation guards
  5. apply suppression and shared-line reservation
  6. format for the target channel
  7. send, then commit the provider receipt

Test every boundary with duplicate events and a stale generation. Conversation safety fails closed when identity or ownership cannot be proven.

On this page