Safety
Handle guardian events and calls to action, and know which safety behavior Doctronic provides and which your product owns.
The chat stream carries typed control events alongside assistant text. Route guardian and
skill_code.cta through their own code paths, separate from the code that renders messages.
event: guardian
data: {"type":"guardian","guardianId":"emergency_breathing","message":"Please call emergency services now."}
Decide from events, not text
Do not parse assistant text to decide whether to escalate, end a consultation, or book care.
Do not replay a patient turn or send a message automatically in response to a guardian event.
Guardian events
The stream emits guardian when Doctronic detects a safety condition. The event has two fields:
| Field | Use |
|---|---|
guardianId | Stable identifier for the condition. Branch on it and record it. |
message | Patient-facing text for your safety path. Show it without changing its meaning. |
When a guardian event arrives:
- Pause any routine flow that conflicts with your safety behavior, such as a booking prompt or a call to action from the same turn.
- Run the presentation and escalation behavior you agreed with Doctronic for that
guardianId. - Record the event type,
guardianId, chat ID, and timestamp in your telemetry, without patient content or the API token.
A guardian event takes precedence over a routine next step, even when another event or message in
the same turn suggests one. Route it from the guardian branch of your
stream parser.
Calls to action
The stream emits skill_code.cta when an end-of-flow action is available, such as seeing a
Doctronic doctor or booking an in-person visit.
event: skill_code.cta
data: {"type":"skill_code.cta","skillCode":"109","widget":"cta_doctor_visit_in_person_widget","text":"See doctor in person"}
| Field | Use |
|---|---|
skillCode | Identifies the action. |
widget | Identifies the interface element for the action. |
text | Optional label you can show on the action. |
Map each skillCode and widget pair you support to a product action, and send every other pair
to a fallback.
// The `skill_code.cta` payload, parsed from the event's `data`.
type SkillCodeCtaEvent = { type: 'skill_code.cta'; skillCode: string; widget: string; text?: string };
// Your product's actions.
type CareActions = { offerBooking(): void; showFallback(label?: string): void };
const ctaActions: Record<string, (care: CareActions) => void> = {
'109:cta_doctor_visit_in_person_widget': (care) => care.offerBooking(),
};
export function presentCallToAction(event: SkillCodeCtaEvent, care: CareActions) {
const action = ctaActions[`${event.skillCode}:${event.widget}`];
if (!action) return care.showFallback(event.text);
return action(care);
}A call to action is an offer to the patient. Booking still needs a ready chat.
Responsibilities
Doctronic provides
- Conversation content through
message.*events, with the role of each message. - A
guardianevent when a safety condition is detected. - Explicit conversation-end, call-to-action, error, and consultation-completion events.
- Consultation documents identified by the completion event.
Your integration owns
- Authenticating the patient before selecting a Doctronic user ID.
- Keeping the API token and webhook secret on your backend.
- Rendering clinical content and events without changing their meaning.
- The patient-facing fallback when a stream, appointment, or document workflow fails.
- Monitoring, local audit records, and access controls in your systems.
Decide with Doctronic
Agree on these before launch, and keep the decisions with your launch evidence:
- Presentation and escalation behavior for each
guardianevent. - Supported call-to-action values and their fallback.
- Patient messaging and support ownership.
- Patient-facing Doctronic attribution, placement, and wording.
- Clinical context you send and the destinations you send data to.
- Webhook events and operational contacts.
- Integration-specific evaluation cases.
- Rollout, pause, and rollback controls.
Patient experience
Your web or mobile client displays the conversation and sends patient input through your backend. Drive each interface state from an event or API response:
| Interface state | Driven by |
|---|---|
| Starting or reconnecting a conversation | POST /chats/ and GET /chats/{chatId}/messages/ |
| Streaming a message | message.start (with its role), message.content, and message.stop |
| Safety path | guardian |
| Call to action | skill_code.cta |
| Conversation ended without a consultation document | conversation.end with no artifact IDs |
| Consultation documents still processing | 202 from artifact retrieval |
| Appointment changes | The appointment resource or webhooks |
| Recoverable stream error or dropped connection | error events and transcript reconciliation (stream errors) |
Send the client only what the interface needs. Check it for accessibility:
- Announce streamed content without repeatedly moving keyboard focus.
- Show status as visible text in addition to color or animation.
- Keep safety messages and calls to action available to assistive technology.
- Support keyboard navigation and sufficient target sizes on mobile.
- Let patients recover from a dropped connection with the visible transcript intact.
- Test long clinical content, large text sizes, reduced motion, and narrow screens.
Fallbacks
Decide what your product does in each case:
| Situation | Decide |
|---|---|
A guardianId your product has no specific behavior for | The default safety presentation |
A skillCode or widget your product doesn't support | The fallback action and label |
A stream that closes before message.stop | How to show the partial message and recover |
A recoverable error without retryAfterSeconds | Your bounded retry policy |
| A prolonged loss of connectivity | What the patient sees and how they resume |
A patient who returns after conversation.end | Whether to start a new chat or show the ended one |
Limits
- The API has no
guardianacknowledgement endpoint. - The API has no external emergency-service integration or general-purpose escalation destination. Your agreed safety behavior defines where escalation goes.
- The API leaves the patient interface to your product.