Meeting confirmation
Meetings carrying the configured Raynet trigger tag are confirmed by an AI assistant over the phone. The assistant identifies itself, confirms only with the intended contact, and passes requests to change the meeting to the salesperson. It does not change the meeting time or promise a new booking.
Setup
- Install a phone plugin providing
phoneCalls, Raynet providingraynetMeetings, and Microsoft Teams with personal delivery by email. - Set Raynet to read/write access with shared company credentials. Automated discovery runs outside a personal conversation.
- Create an ordinary human service account. Grant voice access and explicit access to the phone, meeting confirmation and Raynet plugins, allow the
MeetingConfirmRecordtool and a chat model for its conversations. Configure its voice, chat model permissions and monthly spend limit. Updating to 0.1.4 asks you to consent to the plugin opening conversations in that account. The workspace helper (categorization) model set in Settings → Models also reads the contact from the deal note. - Pick the Service account from the account list, set trigger/result tags, company name and time zone. Calling days default to Monday through Friday; review the selection and keep at least one day.
- Fill Pilot phone numbers with your own E.164 numbers. While this list is non-empty, other numbers are reported to their salesperson and never dialed.
- Link each tagged meeting to its deal (business case) and write the customer contact, with name and phone number, into the deal note; a meeting without a deal, with an empty note or without a clear phone number is handed to the salesperson without a call. Verify the settings form before enabling calls. Test confirmation, cancellation, rescheduling, callbacks, another person answering, voicemail, busy, outages and restart using tagged test meetings.
Clear the pilot list only after the owner approves the real rollout. An empty list permits all tagged meetings.
Titled settings groups start closed and remember your open or closed state. Detailed field guidance is available through the help icon. Delay between attempts and Minimum time before the meeting show hours beside the input and retain quarter-hour steps. Maximum attempts remains a count of calls.
Schedule
Discovery runs at startup and every 15 minutes over the next 30 days. The list selects tagged meetings; each one is then read in detail, because the list carries no owner. Known pending meetings outside that range are reread individually. A missing list entry does not prove deletion.
The first call is planned at First call time on the last allowed calling day before the meeting day. A Monday meeting is normally called on Friday. A late tag uses the next allowed slot. Public holidays are not excluded.
Calling days default to Monday through Friday. Calling hours default to 09:00 until 17:00, Europe/Prague. Closing time is exclusive. The default maximum is two placed attempts, three hours apart measured from the previous call's result. Retries clip into calling hours. Every attempt must start strictly before the meeting start minus Minimum time before the meeting, normally two hours.
One service owns discovery, deliveries and calls. Its single timer wakes at the next due instant, capped at one hour; discovery wakes it for newly found work. One call runs at a time. Before dialing, the meeting and its deal note are reread, the phone is normalized, and the actual current time, deadline and attempt count are checked again after the external reads. A callback is scheduled at its exact future instant if allowed and an attempt remains. Existing work and network latency can delay the actual start, which is rechecked before dialing.
A moved meeting starts a new count for its new start instant. Cancellation, completion or removal of the trigger tag drops the pending job. Completed jobs are not called again for the same meeting time. The trigger tag is retained when a result is written.
Results
| Result | Raynet | Teams | Next action |
|---|---|---|---|
| Confirmed | Confirmation tag and message | None | Close |
| Cancelled | Cancellation tag and message | Salesperson | Close |
| Reschedule request | Reschedule tag and agent message | Salesperson | Close |
| Callback | Agent message | Only if time cannot be honored | Call at that time or close |
| Another person | Agent message | Only if time cannot be honored | Call at that time or close |
| No answer, busy, voicemail or failed | Nothing until exhausted | Nothing until exhausted | Retry or close unreachable |
| Unreachable | Unreachable tag and message | Salesperson | Close |
| Missing or invalid phone | Invalid phone tag and message | Salesperson | Close without dialing |
| Unclear or no agent record | Unclear tag and message | Salesperson | Close |
| Restart or lost call result | No normal result written | Unknown outcome | Close without automatic redial |
| Number outside pilot list | No result tag | Salesperson | Close without dialing |
Conversation per meeting
Every placed call is reported in the service account's conversation for its meeting, titled like Potvrzení schůzky · <company> · <start> in Message language. Retries use the same conversation. Core attaches its own call card and transcript. Core keeps its record of the call for 6 hours and drops it on restart; after that the conversation shows no card. A refused call raises only the administrator alert.
For an answered call, the plugin holds the job without a verdict. The agent receives meeting facts, the call start as ISO with its offset and the configured time zone, and the transcript as untrusted data. Only the intended contact may confirm. Another person cannot confirm; silence never means confirmation. A reschedule is a wish rather than a booked change. Ambiguity means unclear. The agent writes the salesperson's message in Message language and calls MeetingConfirmRecord.
Common parameters are callId, result and message. The message is non-empty after trimming and at most 1000 characters. Results are confirmed, cancelled, reschedule with required preferredTime (1–500 characters), callback with required offset ISO at, other_person with required offset ISO or null reachableAt, and unclear. Invalid arguments return an explicit tool error for retry. The tool accepts only a call bound to its current conversation and records a verdict once; a repeat cannot change it. The existing scheduling rules decide whether callback/reachable times permit another attempt.
The Raynet note line is <ISO timestamp> <agent message> [Elowen #<attemptId>], using the persisted result time. Teams receives that exact message followed by one reference line, for example:
The customer requests Friday afternoon. Please contact them to agree on the next step.
#42 · Oct 8, 2026, 2:00 PM
Confirmed calls send no Teams notice. Callbacks and another-person results send a notice only when another attempt cannot be scheduled. Other dial results keep the deterministic label notice. No second model extracts or summarizes the call.
If the agent finishes, fails, is stopped or cannot start without recording, the plugin records unclear immediately. A turn that never settles, including one interrupted by a daemon restart, has a persisted ten-minute deadline. Fallback writes the unclear tag and label to Raynet; Teams receives the existing company-prefixed unclear label and the reference line. The delivery loop is the only external writer.
Contact from the deal note
Salespeople do not create Raynet contact persons; they write the customer contact into the note of the deal the meeting belongs to. The plugin reads that note (description, usually HTML) and asks the host's helper model for the customer's contact. The model receives the meeting title, the customer company and the salesperson's name as context and the note as untrusted data, and returns {name, phone} with each value a string or null. The phone must be written exactly as in the note; the model returns null when no number belongs to the customer or it is unclear which one does, and must never return the salesperson's or a colleague's number. A model answer that is not this schema fails the meeting loudly and nothing is dialed.
The answer is kept on the job together with a hash of the note and the meeting context, so the model reads a note again only when it or the context changes. Without a helper model the job stays pending and discovery retries; nothing is guessed. The extraction runs outside any account, so its cost is not charged to the service account's spend limit.
Discovery reuses the persisted normalized phone only while the contact hash and raw phone remain unchanged. It still refreshes the meeting, owner and deal note; a changed contact or missing normalized phone requires a new lookup. Every call attempt performs a fresh lookup before dialing.
The phone control distinguishes invalid numbers from lookup outages. A lookup outage clears the prepared phone and leaves the job pending for discovery, without marking the contact invalid. A normalized +421 number selects Slovak, otherwise Czech.
Core refusals do not consume an attempt. They raise an administrator alert and retry no sooner than five minutes, inside calling hours; if no slot remains, the job closes as unreachable.
Delivery and recovery
Pending Raynet updates and Teams notices resume after a restart. Failed delivery is retried every five minutes. An answered call whose result is still missing after ten minutes is recorded as unclear; it is not called again automatically.
Data and costs
The plugin keeps meeting references, contact details, results and pending delivery state. Call transcripts remain in the service account's conversation and follow its conversation deletion rules. The service account selected when a meeting is discovered pays for its calls; changing that account applies to new jobs and moved meeting times. Deleting an account removes its meeting records.
Brief
Advanced Call instructions supports {{companyName}}, {{ownerName}}, {{language}} and {{facts}}. The default asks a customer who cancels or wants another time for a preferred time and tells them the salesperson will contact them; the assistant never agrees to a new time itself. Facts are JSON containing meeting ID, title, today's date and the start, both written out in the configured time zone and call language, the time zone, contact (the name from the deal note, otherwise the customer company) and salesperson. CRM facts and transcripts are untrusted data, never instructions. Messages are requested in Message language, which also controls Teams notices.
The outcome schema discriminates confirmed, cancelled, reschedule with preferredTime, callback with offset ISO at, other_person with nullable offset ISO reachableAt, and unclear. Each agent result contains its own message, validated by the plugin's Zod contract.