Participants & Identity¶
Participant ¶
Bases: BaseModel
A participant in a room conversation.
Identity ¶
Bases: BaseModel
A resolved user identity.
IdentityResult ¶
Bases: BaseModel
Result of identity resolution.
IdentityHookResult ¶
IdentityResolver ¶
Bases: ABC
Resolves user identity from inbound messages.
resolve
abstractmethod
async
¶
Resolve the identity of an inbound message sender.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
InboundMessage
|
The inbound message with sender information. |
required |
context
|
RoomContext
|
Current room context (room, bindings, participants). |
required |
Returns:
| Type | Description |
|---|---|
IdentityResult
|
An identity result indicating identified, ambiguous, pending, |
IdentityResult
|
unknown, or rejected status. |
MockIdentityResolver ¶
Bases: IdentityResolver
Resolves identity from a pre-configured mapping.
Supports three resolution outcomes:
- Identified: sender_id found in mapping → single identity.
- Ambiguous: sender_id found in ambiguous → multiple candidates.
- Unknown/Pending: no match → status controlled by unknown_status.
Verification¶
Verification ¶
Bases: BaseModel
An identity's verification, valid on every channel its addresses reach (§11.7.1).
method
class-attribute
instance-attribute
¶
The integrator's name for how it was proven ("link", "code", "sso").
verified_via
class-attribute
instance-attribute
¶
The channel the completing request was opened on.
ended_reason
class-attribute
instance-attribute
¶
Why it ended: "expired", "revoked", "failed".
request_id
class-attribute
instance-attribute
¶
The request open for the identity, if any.
completed_request_id
class-attribute
instance-attribute
¶
The request that completed the verification: its end is announced in that request's room, on its channel.
VerificationRequest ¶
Bases: BaseModel
A request asking an identified sender to prove who they are (§11.7.2).
The secret is never stored: only its hash, salted with the request's id.
window_start
instance-attribute
¶
When the message that opened it was received: the start of the window whose held messages are released once verified (§11.7.6).
VerificationPolicy ¶
Bases: BaseModel
How long a verification and its requests last, and how many attempts (§11.7).
ttl
class-attribute
instance-attribute
¶
Seconds a completed verification stays in force.
request_ttl
class-attribute
instance-attribute
¶
Seconds a request may be completed in.
code_request_ttl
class-attribute
instance-attribute
¶
Seconds a code request may be completed in: a code is short (§11.7.7).
max_attempts
class-attribute
instance-attribute
¶
Wrong secrets a request accepts before it fails.
code_length
class-attribute
instance-attribute
¶
Digits of a code sent for the person to reply with.
release_on_verify
class-attribute
instance-attribute
¶
Whether the messages held during a request are released to the room's agents when it completes (RFC §11.7.6).
release_max_messages
class-attribute
instance-attribute
¶
At most this many held messages are released, the latest ones.
release_max_age
class-attribute
instance-attribute
¶
Held messages older than this many seconds are not released.
hold_unverified
class-attribute
instance-attribute
¶
Whether an unverified sender's message is held from the room's agents unless an ON_VERIFICATION_REQUIRED hook passes it (RFC §11.7.3); False only labels it.
VerificationRefusedError ¶
Bases: RoomKitError
A verification request could not be completed (RFC §11.7.2).
reason names why: not_found (no such request in the caller's
organization), not_open (completed, failed, expired or cancelled
already), expired (its time ran out now), mismatch (a wrong secret,
counted as an attempt) or failed (the wrong secret that used up its
attempts).
Identity Hooks¶
Identity hooks (ON_IDENTITY_AMBIGUOUS, ON_IDENTITY_UNKNOWN) allow custom handling when the identity resolver returns ambiguous or unknown results.
Basic Usage¶
from roomkit import RoomKit, HookTrigger
from roomkit.models.identity import IdentityHookResult
kit = RoomKit(identity_resolver=my_resolver)
@kit.identity_hook(HookTrigger.ON_IDENTITY_AMBIGUOUS)
async def resolve_ambiguous(event, ctx, id_result):
# Custom logic to resolve ambiguous identity
if len(id_result.candidates) == 1:
return IdentityHookResult.resolved(id_result.candidates[0])
return IdentityHookResult.pending(candidates=id_result.candidates)
Filtering Identity Hooks¶
Identity hooks support filtering by channel_types, channel_ids, and directions, just like regular hooks. This allows you to target identity resolution logic to specific channels.
from roomkit import ChannelType, HookTrigger
from roomkit.models.enums import ChannelDirection
# Only run for SMS inbound messages
@kit.identity_hook(
HookTrigger.ON_IDENTITY_AMBIGUOUS,
channel_types={ChannelType.SMS},
directions={ChannelDirection.INBOUND},
)
async def resolve_sms_identity(event, ctx, id_result):
# Only called for SMS inbound events
return IdentityHookResult.pending(
display_name=ctx.room.metadata.get("phone_number"),
candidates=id_result.candidates,
)
# Only run for specific channel IDs
@kit.identity_hook(
HookTrigger.ON_IDENTITY_UNKNOWN,
channel_ids={"sms-support", "sms-sales"},
)
async def handle_unknown_support(event, ctx, id_result):
# Only called for support/sales SMS channels
return IdentityHookResult.reject("Unknown sender not allowed")
Filter Parameters¶
| Parameter | Type | Description |
|---|---|---|
channel_types |
set[ChannelType] \| None |
Only run for events from these channel types (None = all) |
channel_ids |
set[str] \| None |
Only run for events from these channel IDs (None = all) |
directions |
set[ChannelDirection] \| None |
Only run for events with these directions (None = all) |
All specified filters must match for the hook to be invoked. If a filter is None, it matches all values.
Use Cases¶
SMS-only identity resolution:
@kit.identity_hook(
HookTrigger.ON_IDENTITY_AMBIGUOUS,
channel_types={ChannelType.SMS, ChannelType.EMAIL},
directions={ChannelDirection.INBOUND},
)
async def resolve_transport_identity(event, ctx, id_result):
# Identity resolution for transport channels only
# WebSocket/AI channels are already authenticated
...
Channel-specific rejection: