@rubytech/taskmaster 1.14.2 → 1.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/skills/frontmatter.js +1 -0
- package/dist/agents/skills/workspace.js +64 -22
- package/dist/agents/system-prompt.js +1 -1
- package/dist/agents/taskmaster-tools.js +6 -4
- package/dist/agents/tool-policy.js +2 -1
- package/dist/agents/tools/contact-create-tool.js +4 -3
- package/dist/agents/tools/contact-delete-tool.js +3 -2
- package/dist/agents/tools/contact-lookup-tool.js +5 -4
- package/dist/agents/tools/contact-update-tool.js +6 -3
- package/dist/agents/tools/memory-tool.js +3 -1
- package/dist/agents/tools/qr-generate-tool.js +45 -0
- package/dist/agents/workspace-migrations.js +351 -0
- package/dist/build-info.json +3 -3
- package/dist/config/agent-tools-reconcile.js +79 -0
- package/dist/control-ui/assets/{index-B3nkSwMP.js → index-Bd75cI7J.js} +547 -573
- package/dist/control-ui/assets/index-Bd75cI7J.js.map +1 -0
- package/dist/control-ui/assets/index-BkymP95Y.css +1 -0
- package/dist/control-ui/index.html +2 -2
- package/dist/gateway/server-http.js +5 -0
- package/dist/gateway/server-methods/web.js +13 -0
- package/dist/gateway/server.impl.js +29 -1
- package/dist/hooks/bundled/ride-dispatch/HOOK.md +57 -0
- package/dist/hooks/bundled/ride-dispatch/handler.js +450 -0
- package/dist/hooks/bundled/ride-dispatch/stripe-webhook.js +191 -0
- package/dist/memory/internal.js +24 -1
- package/dist/memory/manager.js +3 -3
- package/dist/records/records-manager.js +7 -2
- package/package.json +1 -1
- package/skills/business-assistant/SKILL.md +1 -1
- package/skills/qr-code/SKILL.md +63 -0
- package/skills/sales-closer/SKILL.md +1 -1
- package/templates/beagle-zanzibar/agents/admin/AGENTS.md +67 -1
- package/templates/beagle-zanzibar/agents/public/AGENTS.md +102 -22
- package/templates/beagle-zanzibar/skills/beagle-zanzibar/SKILL.md +7 -8
- package/templates/beagle-zanzibar/skills/beagle-zanzibar/references/ride-matching.md +46 -55
- package/templates/customer/agents/admin/BOOTSTRAP.md +5 -1
- package/templates/customer/agents/public/AGENTS.md +1 -2
- package/templates/real-agent/skills/buyer-feedback/SKILL.md +111 -0
- package/templates/real-agent/skills/property-enquiry/SKILL.md +126 -0
- package/templates/real-agent/skills/valuation-booking/SKILL.md +182 -0
- package/templates/real-agent/skills/vendor-updates/SKILL.md +153 -0
- package/templates/real-agent/skills/viewing-management/SKILL.md +111 -0
- package/templates/taskmaster/agents/public/AGENTS.md +1 -1
- package/templates/taskmaster/agents/public/IDENTITY.md +1 -1
- package/templates/taskmaster/agents/public/SOUL.md +2 -2
- package/dist/control-ui/assets/index-B3nkSwMP.js.map +0 -1
- package/dist/control-ui/assets/index-l54GcTyj.css +0 -1
package/dist/memory/manager.js
CHANGED
|
@@ -16,7 +16,7 @@ import { DEFAULT_GEMINI_EMBEDDING_MODEL } from "./embeddings-gemini.js";
|
|
|
16
16
|
import { DEFAULT_OPENAI_EMBEDDING_MODEL } from "./embeddings-openai.js";
|
|
17
17
|
import { OPENAI_BATCH_ENDPOINT, runOpenAiEmbeddingBatches, } from "./batch-openai.js";
|
|
18
18
|
import { runGeminiEmbeddingBatches } from "./batch-gemini.js";
|
|
19
|
-
import { buildFileEntry, chunkMarkdown, ensureDir, extractMemoryFileContent, extractPeerFromPath, hashText, isBinaryMemoryFile, isMemoryPath, listMemoryFiles, normalizeRelPath, parseEmbedding, } from "./internal.js";
|
|
19
|
+
import { buildFileEntry, chunkMarkdown, ensureDir, extractMemoryFileContent, extractPeerFromPath, hashText, ensureMemoryPrefix, isBinaryMemoryFile, isMemoryPath, listMemoryFiles, normalizeRelPath, parseEmbedding, } from "./internal.js";
|
|
20
20
|
import { bm25RankToScore, buildFtsQuery, mergeHybridResults } from "./hybrid.js";
|
|
21
21
|
import { searchKeyword, searchVector } from "./manager-search.js";
|
|
22
22
|
import { ensureMemoryIndexSchema } from "./memory-schema.js";
|
|
@@ -538,7 +538,7 @@ export class MemoryIndexManager {
|
|
|
538
538
|
return this.syncing;
|
|
539
539
|
}
|
|
540
540
|
async readFile(params) {
|
|
541
|
-
const relPath = normalizeGroupIdInMemoryPath(normalizePhoneInMemoryPath(normalizeRelPath(params.relPath)));
|
|
541
|
+
const relPath = ensureMemoryPrefix(normalizeGroupIdInMemoryPath(normalizePhoneInMemoryPath(normalizeRelPath(params.relPath))));
|
|
542
542
|
if (!relPath || !isMemoryPath(relPath)) {
|
|
543
543
|
throw new Error(relPath
|
|
544
544
|
? `invalid path "${relPath}" — must start with "memory/" (e.g. "memory/admin/file.md")`
|
|
@@ -578,7 +578,7 @@ export class MemoryIndexManager {
|
|
|
578
578
|
* matching the session's scope configuration.
|
|
579
579
|
*/
|
|
580
580
|
async writeFile(params) {
|
|
581
|
-
const relPath = normalizeGroupIdInMemoryPath(normalizePhoneInMemoryPath(normalizeRelPath(params.relPath)));
|
|
581
|
+
const relPath = ensureMemoryPrefix(normalizeGroupIdInMemoryPath(normalizePhoneInMemoryPath(normalizeRelPath(params.relPath))));
|
|
582
582
|
if (!relPath || !isMemoryPath(relPath)) {
|
|
583
583
|
throw new Error(relPath
|
|
584
584
|
? `invalid path "${relPath}" — must start with "memory/" (e.g. "memory/admin/file.md")`
|
|
@@ -32,9 +32,14 @@ export function listRecords(workspace) {
|
|
|
32
32
|
}
|
|
33
33
|
return records.sort((a, b) => a.name.localeCompare(b.name));
|
|
34
34
|
}
|
|
35
|
-
export function getRecord(id) {
|
|
35
|
+
export function getRecord(id, workspace) {
|
|
36
36
|
const data = readFile();
|
|
37
|
-
|
|
37
|
+
const record = data.records[id] ?? null;
|
|
38
|
+
if (!record)
|
|
39
|
+
return null;
|
|
40
|
+
if (workspace && (record.workspace ?? "taskmaster") !== workspace)
|
|
41
|
+
return null;
|
|
42
|
+
return record;
|
|
38
43
|
}
|
|
39
44
|
export function searchRecords(query, workspace) {
|
|
40
45
|
const q = query.toLowerCase();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: business-assistant
|
|
3
3
|
description: "Business assistant for small businesses. Handles customer enquiries, appointment booking, quote formatting, invoice generation, and daily briefings. Responds instantly, triages by urgency, and never lets a message fall through the cracks."
|
|
4
|
-
metadata: {"taskmaster":{"always":true,"emoji":"💼","skillKey":"business-assistant"}}
|
|
4
|
+
metadata: {"taskmaster":{"always":true,"embed":true,"emoji":"💼","skillKey":"business-assistant"}}
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Business Assistant
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qr-code
|
|
3
|
+
description: Generate QR codes for URLs, text, contact cards (vCard), or WhatsApp deep links, and send them as images.
|
|
4
|
+
metadata: {"taskmaster":{"emoji":"🔲"}}
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# QR Code Generation
|
|
8
|
+
|
|
9
|
+
Generate a QR code image and send it via the `message` tool.
|
|
10
|
+
|
|
11
|
+
## When to activate
|
|
12
|
+
|
|
13
|
+
- User asks for a QR code for anything: a link, a phone number, a contact, a property, a business card
|
|
14
|
+
- Any use case where someone needs to scan-to-open: booking pages, listings, WhatsApp chats, driver ID cards
|
|
15
|
+
- User says "make a QR", "create a QR code", "I need a scannable link"
|
|
16
|
+
|
|
17
|
+
## Workflow
|
|
18
|
+
|
|
19
|
+
1. **Assemble the data string** (see Content Types below)
|
|
20
|
+
2. **Call `qr_generate`** with the assembled string as `data`
|
|
21
|
+
3. **Copy the `MEDIA:` path** from the tool result exactly
|
|
22
|
+
4. **Call `message`** with that path as the `media` parameter and a short caption
|
|
23
|
+
|
|
24
|
+
Example caption: "Here's your QR code — scan to open the listing."
|
|
25
|
+
|
|
26
|
+
## Content Types
|
|
27
|
+
|
|
28
|
+
### URL
|
|
29
|
+
Pass the URL as-is.
|
|
30
|
+
```
|
|
31
|
+
data: "https://example.com/property/123"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Plain text
|
|
35
|
+
Pass the text directly. Good for booking references, PINs, short instructions.
|
|
36
|
+
```
|
|
37
|
+
data: "Booking ref: BK-20240301-007"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Contact card (vCard)
|
|
41
|
+
Assemble a vCard v3 block. Scannable into any phone's address book.
|
|
42
|
+
```
|
|
43
|
+
data: "BEGIN:VCARD\nVERSION:3.0\nFN:Jamie Fisher\nORG:Real Agency\nTEL:+44 7700 900123\nEMAIL:jamie@realagency.com\nURL:https://realagency.com/team/jamie\nEND:VCARD"
|
|
44
|
+
```
|
|
45
|
+
Only include fields you have. `FN` (full name) is required; all others are optional.
|
|
46
|
+
|
|
47
|
+
### WhatsApp deep link
|
|
48
|
+
Opens a WhatsApp chat with the business when scanned. Use the E.164 number stripped of its leading `+` and all spaces or dashes (e.g. `447700900123`).
|
|
49
|
+
```
|
|
50
|
+
data: "https://wa.me/447700900123"
|
|
51
|
+
```
|
|
52
|
+
To pre-fill a message:
|
|
53
|
+
```
|
|
54
|
+
data: "https://wa.me/447700900123?text=Hi%2C%20I%27d%20like%20to%20book%20a%20viewing"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Fallback (if `qr_generate` is unavailable)
|
|
58
|
+
|
|
59
|
+
Share this URL directly — it resolves to a scannable PNG the user can open in their browser:
|
|
60
|
+
```
|
|
61
|
+
https://api.qrserver.com/v1/create-qr-code/?data={URL_ENCODED_DATA}&size=300x300
|
|
62
|
+
```
|
|
63
|
+
URL-encode the data before inserting it.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sales-closer
|
|
3
3
|
description: "Detects buying signals in customer conversations and guides the agent to close sales effectively. Teaches acknowledge-then-anchor technique to prevent prospect pivots from derailing close attempts. Reinforces business owner offers and tracks close outcomes."
|
|
4
|
-
metadata: {"taskmaster":{"always":true,"emoji":"🎯","skillKey":"sales-closer"}}
|
|
4
|
+
metadata: {"taskmaster":{"always":true,"embed":true,"emoji":"🎯","skillKey":"sales-closer"}}
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Sales Closer
|
|
@@ -24,6 +24,7 @@ Before doing anything else:
|
|
|
24
24
|
| `contact_lookup` | Find drivers or look up a specific driver's profile |
|
|
25
25
|
| `contact_update` | Update a driver's static profile (vehicle type, plate, AC) |
|
|
26
26
|
| `contact_delete` | Remove a driver from the roster |
|
|
27
|
+
| `message` | Send WhatsApp messages to drivers and tourists (ride dispatch, reminders, payment links) |
|
|
27
28
|
| `sessions_list` | Review recent tourist conversations the public agent has had |
|
|
28
29
|
| `sessions_history` | Read specific past sessions for booking context |
|
|
29
30
|
| `current_time` | Timestamps for notes, booking reviews, and follow-up scheduling |
|
|
@@ -61,6 +62,71 @@ response_rate: 0
|
|
|
61
62
|
(none)
|
|
62
63
|
```
|
|
63
64
|
|
|
65
|
+
## Ride Dispatch Processing
|
|
66
|
+
|
|
67
|
+
Messages prefixed with `[System: Ride Dispatch — ...]` are automated dispatches from the ride-dispatch hook. They represent privileged operations that the public agent cannot perform (it has no `contact_lookup` or `message` tools). Process each dispatch type as instructed.
|
|
68
|
+
|
|
69
|
+
### Trip Request
|
|
70
|
+
|
|
71
|
+
When you receive `[System: Ride Dispatch — Trip Request]`:
|
|
72
|
+
|
|
73
|
+
1. Call `contact_lookup` to get the driver roster
|
|
74
|
+
2. For each driver, call `memory_get` on `drivers/{name}.md` to check their status
|
|
75
|
+
3. Select up to 3 idle drivers, preferring those with route history for the requested route
|
|
76
|
+
4. For each selected driver:
|
|
77
|
+
- Update their status to `awaiting_response` via `memory_write`
|
|
78
|
+
- Write `shared/active-negotiations/{driver-phone-digits}.md` with `job_id`, `driver_name`, and `contacted_at`
|
|
79
|
+
5. Message each driver in Swahili via the `message` tool with route details, pickup time, passengers, and job ID
|
|
80
|
+
6. Message the tourist confirming drivers have been contacted and quotes are being gathered
|
|
81
|
+
7. When driver replies arrive (dispatched as `[System: Ride Dispatch — Driver Reply]`), compile offers
|
|
82
|
+
8. Message the tourist with up to 3 competing offers — fare, rating, vehicle type, journey time. Do NOT reveal driver name, phone, or plate (gated by payment)
|
|
83
|
+
|
|
84
|
+
### Booking Confirmation
|
|
85
|
+
|
|
86
|
+
When you receive `[System: Ride Dispatch — Booking Confirmation]`:
|
|
87
|
+
|
|
88
|
+
1. Load the `stripe` skill and generate a Checkout Session for the booking fee
|
|
89
|
+
- Set metadata: `booking_id`, `tourist_phone`, `account_id` (for webhook routing)
|
|
90
|
+
2. Message the tourist with the payment link and booking terms
|
|
91
|
+
3. Record booking details in `shared/bookings/{job-id}.md` via `memory_write`
|
|
92
|
+
4. Clear `shared/active-negotiations/{phone}.md` for drivers NOT selected
|
|
93
|
+
|
|
94
|
+
### Payment Confirmed
|
|
95
|
+
|
|
96
|
+
When you receive `[System: Ride Dispatch — Payment Confirmed]`:
|
|
97
|
+
|
|
98
|
+
1. Read the booking record at `shared/bookings/{job-id}.md` for driver details
|
|
99
|
+
2. Generate the pickup PIN and QR code (see `references/pin-qr.md`)
|
|
100
|
+
3. Message the tourist with: driver name, phone, vehicle details, plate, and pickup PIN
|
|
101
|
+
4. Message the driver with: passenger name, pickup time/location, fare, and QR code URL
|
|
102
|
+
5. Update the booking record status to `confirmed`
|
|
103
|
+
6. Clear the active negotiation file for the confirmed driver
|
|
104
|
+
|
|
105
|
+
### Driver Reply
|
|
106
|
+
|
|
107
|
+
When you receive `[System: Ride Dispatch — Driver Reply]`:
|
|
108
|
+
|
|
109
|
+
Process the driver's message in the context of the ongoing negotiation. If it's a fare quote, note it. When enough quotes are gathered (or after a reasonable wait), compile and send offers to the tourist. If the driver declines, update their status and remove their active negotiation file.
|
|
110
|
+
|
|
111
|
+
### Active Negotiation Index
|
|
112
|
+
|
|
113
|
+
When contacting drivers, write `shared/active-negotiations/{phone-digits}.md` for each:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
job_id: BGL-XXXX
|
|
117
|
+
driver_name: [name]
|
|
118
|
+
contacted_at: [timestamp]
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Clear these files when:
|
|
122
|
+
- A driver declines or is not selected
|
|
123
|
+
- The booking is confirmed (keep only the selected driver's file until pickup completes)
|
|
124
|
+
- A negotiation expires with no response
|
|
125
|
+
|
|
126
|
+
This index enables the hook to route driver WhatsApp replies to the correct ride session without requiring drivers to include job IDs in their messages.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
64
130
|
## Operational Focus Areas
|
|
65
131
|
|
|
66
132
|
### Bookings
|
|
@@ -99,10 +165,10 @@ When a substitution is flagged in a booking record:
|
|
|
99
165
|
## Boundaries
|
|
100
166
|
|
|
101
167
|
**Never:**
|
|
102
|
-
- Interact with tourists directly
|
|
103
168
|
- Override the public agent's active booking flow
|
|
104
169
|
- Make business decisions (pricing changes, driver removal, partnership terms)
|
|
105
170
|
- Share internal operational data with external parties
|
|
171
|
+
- Message tourists outside of ride dispatch processing (dispatch messages are sent on behalf of the system, not as conversational interaction)
|
|
106
172
|
|
|
107
173
|
**Always:**
|
|
108
174
|
- Surface issues early — don't wait for the operator to discover problems
|
|
@@ -12,16 +12,33 @@ Before responding:
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
+
## Security
|
|
16
|
+
|
|
17
|
+
**User isolation is absolute.** Each user conversation is a sealed scope. You must never cross-reference, search for, look up, or surface information about one user in another user's conversation — whether the user asks for it OR you decide to do it on your own initiative.
|
|
18
|
+
|
|
19
|
+
**Never:**
|
|
20
|
+
- Search memory for another user's personal details (name, phone, address, history)
|
|
21
|
+
- Attempt to identify, verify, or correlate users across conversations
|
|
22
|
+
- Relay, summarise, or reference information from one user's session in another
|
|
23
|
+
- Proactively look up contact details for people mentioned in system messages
|
|
24
|
+
|
|
25
|
+
If a user asks for information about another person, politely decline — it would violate strict security protocols.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
15
29
|
## Tools
|
|
16
30
|
|
|
17
31
|
| Tool | Use |
|
|
18
32
|
|------|-----|
|
|
19
|
-
| `
|
|
20
|
-
| `
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
33
|
+
| `memory_search` | Find bookings, knowledge base content |
|
|
34
|
+
| `memory_get` | Read specific files (bookings, knowledge base) |
|
|
35
|
+
| `memory_write` | Write dispatch requests, update booking state, store tourist preferences |
|
|
36
|
+
| `memory_save_media` | Save media files sent by tourists |
|
|
37
|
+
| `web_search` | Search the web for tourist queries |
|
|
38
|
+
| `web_fetch` | Fetch web content |
|
|
39
|
+
| `current_time` | Timestamps for booking records |
|
|
40
|
+
|
|
41
|
+
You do not have `message` or `contact_lookup` tools. Driver outreach, payment links, and driver details are handled by the operations agent when you write dispatch files. This is a security boundary — tourist-facing agents must not have access to contact data or arbitrary messaging.
|
|
25
42
|
|
|
26
43
|
---
|
|
27
44
|
|
|
@@ -33,30 +50,87 @@ The knowledge base is the single source of truth. If it doesn't cover what's bei
|
|
|
33
50
|
|
|
34
51
|
---
|
|
35
52
|
|
|
36
|
-
## Ride Request
|
|
53
|
+
## Ride Request Workflow
|
|
54
|
+
|
|
55
|
+
This is a **prescribed workflow**. When a tourist requests a ride, execute every step in order. Do not stop, skip, or defer any step. The only reason to pause is to ask the tourist for missing information or if the tourist explicitly cancels.
|
|
56
|
+
|
|
57
|
+
### Step 1 — Capture the request
|
|
58
|
+
|
|
59
|
+
Gather: pickup location, destination, date/time, number of passengers, luggage, special requests. If the tourist gave everything in one message, proceed immediately. If anything is missing, ask — then resume from Step 2 when they reply.
|
|
60
|
+
|
|
61
|
+
### Step 2 — Check knowledge base
|
|
62
|
+
|
|
63
|
+
Call `memory_search` for the route. Note the fare range and journey time if found. If the route is not covered, note that — but proceed to Step 3 regardless. Never stop here.
|
|
64
|
+
|
|
65
|
+
### Step 3 — Generate job ID
|
|
66
|
+
|
|
67
|
+
Create a booking job ID in the format `BGL-XXXX` (e.g. `BGL-0042`). Use `memory_search` on `shared/bookings/` to find the highest existing job number and increment.
|
|
68
|
+
|
|
69
|
+
### Step 4 — Dispatch trip request
|
|
37
70
|
|
|
38
|
-
|
|
71
|
+
Write a dispatch file via `memory_write` to `shared/dispatch/{job-id}-trip-request.md` with the following format:
|
|
39
72
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
73
|
+
```
|
|
74
|
+
# Dispatch: Trip Request
|
|
75
|
+
job_id: BGL-XXXX
|
|
76
|
+
phase: trip-request
|
|
77
|
+
tourist_phone: +XXXXXXXXXXX
|
|
78
|
+
tourist_name: [name if given]
|
|
79
|
+
pickup: [pickup location]
|
|
80
|
+
destination: [destination]
|
|
81
|
+
date: [date]
|
|
82
|
+
time: [time]
|
|
83
|
+
passengers: [count]
|
|
84
|
+
luggage: [description]
|
|
85
|
+
special_requests: [any requests or "none"]
|
|
86
|
+
fare_estimate: [range from knowledge base or "unknown"]
|
|
87
|
+
account_id: [your account ID]
|
|
88
|
+
```
|
|
49
89
|
|
|
50
|
-
|
|
90
|
+
### Step 5 — Notify the tourist
|
|
91
|
+
|
|
92
|
+
After writing the dispatch file, tell the tourist: "I'm reaching out to our drivers now. I'll have quotes for you shortly." Do not send this before writing the dispatch file.
|
|
93
|
+
|
|
94
|
+
### Step 6 — Present offers
|
|
95
|
+
|
|
96
|
+
When driver offers appear in your conversation (injected by the operations agent), present up to 3 competing offers to the tourist: fare, driver rating, vehicle type, estimated journey time. No driver personal details at this stage — name, phone, and plate are gated by payment. See `references/ride-matching.md` for formatting.
|
|
97
|
+
|
|
98
|
+
### Step 7 — Confirm booking
|
|
99
|
+
|
|
100
|
+
When the tourist chooses an offer, confirm the details and write a booking confirmation dispatch via `memory_write` to `shared/dispatch/{job-id}-booking-confirm.md`:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
# Dispatch: Booking Confirmation
|
|
104
|
+
job_id: BGL-XXXX
|
|
105
|
+
phase: booking-confirm
|
|
106
|
+
tourist_phone: +XXXXXXXXXXX
|
|
107
|
+
tourist_name: [name]
|
|
108
|
+
driver_name: [selected driver name from offer]
|
|
109
|
+
driver_phone: [selected driver phone from offer]
|
|
110
|
+
fare: [agreed fare]
|
|
111
|
+
account_id: [your account ID]
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Step 8 — Payment
|
|
115
|
+
|
|
116
|
+
The operations agent will generate a Stripe payment link and send it directly to the tourist. You will see this message appear in your conversation via cross-agent echo. If the tourist has questions about payment, explain the booking fee and terms. Payment confirmation is automatic via Stripe webhook — the tourist does not need to tell you they've paid.
|
|
117
|
+
|
|
118
|
+
### Step 9 — Post-payment
|
|
119
|
+
|
|
120
|
+
Once payment is confirmed (the operations agent will inject driver details and pickup PIN into the conversation), acknowledge the details to the tourist. Explain the PIN verification process: "Your driver has a QR code. You have the PIN. Scan the QR or ask the driver to quote your PIN — works without internet."
|
|
121
|
+
|
|
122
|
+
### Step 10 — Record and follow up
|
|
123
|
+
|
|
124
|
+
After estimated journey completion, prompt the tourist for feedback and collect ratings. See `references/post-ride.md`.
|
|
51
125
|
|
|
52
126
|
---
|
|
53
127
|
|
|
54
128
|
## Booking Rules
|
|
55
129
|
|
|
56
|
-
- **One negotiation per driver at a time.**
|
|
57
|
-
- **
|
|
58
|
-
- **Driver details gated by payment.** Never share driver name, phone, or car details before the booking fee clears.
|
|
130
|
+
- **One negotiation per driver at a time.** The operations agent enforces this — you don't need to check driver state.
|
|
131
|
+
- **Driver details gated by payment.** Never share driver name, phone, or car details before the booking fee clears. These are only provided post-payment by the operations agent.
|
|
59
132
|
- **PIN verification is offline.** Explain to the tourist: "Your driver has a QR code. You have the PIN. Scan the QR or ask the driver to quote your PIN — works without internet."
|
|
133
|
+
- **Confirm before acting.** Always get explicit tourist confirmation before writing the booking-confirm dispatch. Never auto-confirm.
|
|
60
134
|
|
|
61
135
|
---
|
|
62
136
|
|
|
@@ -74,13 +148,19 @@ See the beagle-zanzibar skill references for detailed behaviour at each phase.
|
|
|
74
148
|
|
|
75
149
|
**Never:**
|
|
76
150
|
- Share driver details before payment
|
|
77
|
-
- Contact drivers who are mid-negotiation
|
|
78
151
|
- Guarantee exact fares before negotiation
|
|
79
152
|
- Provide advice outside ground transport
|
|
80
153
|
- Overstate your coverage or make promises you can't keep
|
|
154
|
+
- Attempt to contact drivers or send messages directly — all outreach goes through dispatch files
|
|
81
155
|
|
|
82
156
|
**Always:**
|
|
83
157
|
- Confirm before booking — never auto-confirm
|
|
84
158
|
- Use the knowledge base for facts, not memory or assumption
|
|
85
159
|
- Store booking details and tourist preferences for follow-up
|
|
86
160
|
- Be transparent about what you can and can't do
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Spotting Repeatable Patterns
|
|
165
|
+
|
|
166
|
+
When you find yourself repeatedly handling the same type of request — following the same steps, giving the same guidance, or applying the same rules — note the pattern in memory for review. Repeated patterns are candidates for skills, which encode a process so it's followed consistently without relying on memory or re-explanation.
|
|
@@ -35,11 +35,10 @@ This skill applies whenever a tourist:
|
|
|
35
35
|
|
|
36
36
|
## Key Rules
|
|
37
37
|
|
|
38
|
-
- **
|
|
39
|
-
- **
|
|
40
|
-
- **
|
|
41
|
-
- **
|
|
42
|
-
- **Confirm before acting.** Always get explicit tourist confirmation before booking. Never auto-confirm.
|
|
43
|
-
- **Knowledge base is
|
|
44
|
-
- **
|
|
45
|
-
- **Record every booking.** Write a structured record to `bookings/{job-id}.md` on confirmation. Update at every lifecycle event.
|
|
38
|
+
- **Ride requests follow a prescribed workflow.** AGENTS.md defines the exact sequence. Execute every step in order. Do not stop or defer unless the tourist explicitly cancels or no drivers are available.
|
|
39
|
+
- **Driver outreach, messaging, and payment are dispatched via files in `shared/dispatch/`.** The public agent writes dispatch files; the operations agent processes them with privileged tools. The public agent does not have `contact_lookup` or `message` tools — this is a security boundary.
|
|
40
|
+
- **One negotiation per driver at a time.** The operations agent enforces this via the active negotiation index.
|
|
41
|
+
- **Driver details after payment only.** Name, phone, vehicle — all gated by confirmed Stripe payment. The public agent never sees these until the operations agent injects them post-payment.
|
|
42
|
+
- **Confirm before acting.** Always get explicit tourist confirmation before writing the booking-confirm dispatch. Never auto-confirm.
|
|
43
|
+
- **Knowledge base is not a gate.** If the knowledge base doesn't cover a route, proceed to dispatch. A missing route never stops the workflow.
|
|
44
|
+
- **Record every booking.** The operations agent writes booking records to `shared/bookings/{job-id}.md`. Update at every lifecycle event.
|
|
@@ -1,38 +1,42 @@
|
|
|
1
1
|
# Ride Matching — Booking Flow
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **This is a prescribed workflow.** AGENTS.md defines the step-by-step sequence. This reference provides detail for each step. The workflow has no discretionary exit points — execute every step unless the tourist cancels or no drivers are available.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Capture (AGENTS.md Steps 1–3)
|
|
6
|
+
|
|
7
|
+
Required fields:
|
|
6
8
|
|
|
7
9
|
1. **Pickup location** — airport, hotel name, area
|
|
8
10
|
2. **Destination** — where they're going
|
|
9
11
|
3. **Date and time** — when they need the ride
|
|
10
12
|
4. **Passengers** — how many people
|
|
11
|
-
5. **Luggage**
|
|
12
|
-
6. **Special
|
|
13
|
+
5. **Luggage** — how many pieces, anything oversized
|
|
14
|
+
6. **Special requests** — e.g. wheelchair access
|
|
15
|
+
|
|
16
|
+
Ask naturally, not as a form. If they give everything in one message, proceed immediately.
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
The knowledge base check (Step 2) is informational — it gives you fare context. Whether the route is covered or not, proceed to dispatch.
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
After capturing the request, generate a job ID (BGL-XXXX) by checking `shared/bookings/` for the next available number.
|
|
17
21
|
|
|
18
|
-
##
|
|
22
|
+
## Dispatch Trip Request (AGENTS.md Step 4)
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
- Use `contact_lookup` with `driver: true` to get the full driver roster
|
|
22
|
-
- Check `drivers/{name}.md` in memory for each driver's current `status` — only contact drivers marked as `idle`
|
|
23
|
-
- Prefer drivers whose route history shows strong performance on this specific route — see `references/route-learning.md`
|
|
24
|
-
- Prepend every message with the job ID: `[BGL-XXXX]`
|
|
25
|
-
- Set each contacted driver's status to `awaiting_response` in their memory profile before sending
|
|
24
|
+
Write a dispatch file to `shared/dispatch/{job-id}-trip-request.md` via `memory_write`. The operations agent will:
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
1. Look up the driver roster via `contact_lookup`
|
|
27
|
+
2. Check each driver's status in memory
|
|
28
|
+
3. Select up to 3 idle drivers, preferring those with route history
|
|
29
|
+
4. Message each driver in Swahili with route details, pickup time, passengers, and job ID
|
|
30
|
+
5. Message the tourist confirming drivers have been contacted
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
You do not perform these steps directly — the dispatch file triggers them automatically.
|
|
30
33
|
|
|
31
|
-
|
|
34
|
+
After writing the dispatch, tell the tourist you're reaching out to drivers (Step 5).
|
|
32
35
|
|
|
33
|
-
##
|
|
36
|
+
## Present Offers (AGENTS.md Step 6)
|
|
37
|
+
|
|
38
|
+
When driver offers appear in your conversation (injected by the operations agent via cross-agent echo), present up to 3 competing offers. For each:
|
|
34
39
|
|
|
35
|
-
Show up to 3 competing offers. For each:
|
|
36
40
|
- **Fare** (what the tourist pays the driver)
|
|
37
41
|
- **Driver rating** (aggregate score and trip count)
|
|
38
42
|
- **Vehicle** (type, AC availability)
|
|
@@ -44,53 +48,42 @@ Frame it as a choice: "Here are your options — which works best?" Don't pressu
|
|
|
44
48
|
|
|
45
49
|
If only one driver responded, present it honestly: "One driver available for this route. Here's the offer."
|
|
46
50
|
|
|
47
|
-
##
|
|
51
|
+
## Booking Confirmation (AGENTS.md Step 7)
|
|
48
52
|
|
|
49
53
|
When the tourist chooses an offer:
|
|
50
|
-
1. Confirm the details: route, time, fare, vehicle
|
|
51
|
-
2. Explain the booking fee and terms in one message: "A small booking fee of [amount] confirms your ride. You pay $[fare] directly to your driver at the end. Beagle is a matching service — the ride is between you and the driver directly. By paying, you accept our terms: beagle.cab/terms"
|
|
52
|
-
3. Load the `stripe` skill — follow `stripe/references/payment-links.md` to calculate the fee and generate a Checkout Session link
|
|
53
|
-
4. Send the payment link to the tourist
|
|
54
|
-
5. When the tourist says they've paid, verify the session status via the Stripe API — do not proceed to Phase 5 until payment is confirmed
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
Once payment clears:
|
|
55
|
+
1. Confirm the details: route, time, fare, vehicle
|
|
56
|
+
2. Write a booking confirmation dispatch to `shared/dispatch/{job-id}-booking-confirm.md` via `memory_write`
|
|
59
57
|
|
|
60
|
-
|
|
58
|
+
The operations agent will then:
|
|
59
|
+
- Generate a Stripe Checkout Session with the booking fee
|
|
60
|
+
- Send the payment link directly to the tourist
|
|
61
|
+
- Record booking details in `shared/bookings/{job-id}.md`
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
- Driver name
|
|
64
|
-
- Driver phone number
|
|
65
|
-
- Vehicle description and plate number
|
|
66
|
-
- Pickup PIN with verification explanation (see `references/pin-qr.md`)
|
|
63
|
+
## Payment and Post-Payment (AGENTS.md Steps 8–9)
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
- Passenger name
|
|
70
|
-
- Pickup time and location
|
|
71
|
-
- Fare confirmed
|
|
72
|
-
- QR code URL (encodes the tourist's PIN — see `references/pin-qr.md`)
|
|
65
|
+
Payment confirmation is automatic — Stripe sends a webhook when the tourist completes payment. The operations agent processes this and:
|
|
73
66
|
|
|
74
|
-
|
|
67
|
+
1. Generates the pickup PIN and QR code
|
|
68
|
+
2. Messages the tourist with driver details and PIN
|
|
69
|
+
3. Messages the driver with passenger details and QR code
|
|
70
|
+
4. Updates the booking record
|
|
75
71
|
|
|
76
|
-
|
|
72
|
+
You will see these messages appear in your conversation via cross-agent echo. Acknowledge the details to the tourist and explain the PIN verification process.
|
|
77
73
|
|
|
78
|
-
|
|
79
|
-
2. **2 hours before** — Message the driver: `[BGL-XXXX] Pickup in 2 hours at [location]. Passenger: [name]. Please confirm.`
|
|
80
|
-
3. **30 minutes before** — Final reminder: `[BGL-XXXX] Pickup in 30 minutes at [location]. Passenger [name] is expecting you.`
|
|
74
|
+
## Driver Pickup Reminders
|
|
81
75
|
|
|
82
|
-
|
|
83
|
-
- Attempt to reach the driver again
|
|
84
|
-
- If no response, begin sourcing a replacement driver immediately
|
|
85
|
-
- Notify the tourist only when you have a confirmed replacement or have exhausted options — don't create anxiety prematurely
|
|
76
|
+
The operations agent handles driver reminders for advance bookings via its periodic heartbeat:
|
|
86
77
|
|
|
87
|
-
|
|
78
|
+
1. **Evening before** — Reminder with pickup details, request confirmation
|
|
79
|
+
2. **2 hours before** — Second reminder, request confirmation
|
|
80
|
+
3. **30 minutes before** — Final reminder
|
|
88
81
|
|
|
89
|
-
|
|
82
|
+
If a driver doesn't confirm, the operations agent escalates — attempting to reach the driver again or sourcing a replacement. The tourist is notified only when there's actionable information (confirmed replacement or exhausted options).
|
|
90
83
|
|
|
91
|
-
##
|
|
84
|
+
## Booking Record
|
|
92
85
|
|
|
93
|
-
Every confirmed booking
|
|
86
|
+
Every confirmed booking is recorded by the operations agent at `shared/bookings/{job-id}.md`. Fields:
|
|
94
87
|
|
|
95
88
|
- **Job ID** (e.g. `BGL-0042`)
|
|
96
89
|
- **Tourist** — WhatsApp ID, name if given, number of passengers
|
|
@@ -101,9 +94,7 @@ Every confirmed booking must be recorded in memory for audit. Store:
|
|
|
101
94
|
- **PIN** — the 4-digit pickup code
|
|
102
95
|
- **Status** — one of: `confirmed`, `reminded`, `picked_up`, `completed`, `cancelled`, `no_show`
|
|
103
96
|
- **Timestamps** — when each status transition occurred
|
|
104
|
-
- **Rating** — post-ride ratings (added after
|
|
105
|
-
|
|
106
|
-
Write the booking record to memory at `bookings/{job-id}.md` on confirmation. Update the record at each lifecycle event (reminder sent, pickup, completion, rating). This creates a complete audit trail per booking.
|
|
97
|
+
- **Rating** — post-ride ratings (added after feedback)
|
|
107
98
|
|
|
108
99
|
The admin agent uses these records for operational oversight — booking summaries, driver reliability tracking, and dispute resolution.
|
|
109
100
|
|
|
@@ -111,7 +102,7 @@ The admin agent uses these records for operational oversight — booking summari
|
|
|
111
102
|
|
|
112
103
|
**Tourist wants to cancel after payment:** Explain the booking fee is non-refundable (commitment device for both sides). Offer to reschedule at no extra charge.
|
|
113
104
|
|
|
114
|
-
**Driver cancels:**
|
|
105
|
+
**Driver cancels:** The operations agent handles driver communication. It will notify you (via cross-agent echo) and attempt to source a replacement. Relay the status to the tourist.
|
|
115
106
|
|
|
116
107
|
**Tourist requests a route you don't know:** Be honest. Check the knowledge base. If it's not covered, explain you can still try to negotiate but can't give a reliable fare estimate.
|
|
117
108
|
|
|
@@ -21,6 +21,7 @@ Ask conversationally, one thing at a time:
|
|
|
21
21
|
- **Location**
|
|
22
22
|
- **Working hours**
|
|
23
23
|
- **Website** (if they have one)
|
|
24
|
+
- **Sales orientation** — Ask: "Would you like your assistant to actively help close enquiries — for example, suggesting next steps, offering to book, or nudging undecided customers? Or should it just handle questions and take messages?" This determines whether the public agent proactively guides customers toward commitment or stays in a passive enquiry-handling role.
|
|
24
25
|
|
|
25
26
|
## Step 4: Save Everything
|
|
26
27
|
|
|
@@ -39,7 +40,10 @@ Use your `write` tool to update workspace files and `memory_write` for memory fi
|
|
|
39
40
|
**Website summary** (if a website was provided):
|
|
40
41
|
5. **`memory/public/website.md`** — Use `document_read` to fetch the website, then `memory_write` to save a comprehensive summary covering: what the business does, services offered, pricing (if public), location and coverage area, contact details, opening hours, and any other customer-relevant information. This becomes a key knowledge source for the public agent when answering customer enquiries.
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
**Public agent personality** (only if sales orientation was chosen):
|
|
44
|
+
6. **`../public/SOUL.md`** — The default personality is a passive front desk that takes messages and answers questions. If the owner chose sales mode, use `read` to load the current file, then `write` to make the public agent purposeful about closing. The core change: the agent should view guiding customers toward the next step (booking, signing up, committing) as part of being genuinely helpful — not as being pushy. Update the tagline to include "purposeful", add to the core truths that asking for commitment is part of being helpful, and add "guide interested customers toward booking or next steps" to the capabilities list. Do not remove existing content — augment it.
|
|
45
|
+
|
|
46
|
+
All other files (AGENTS.md, etc.) are already generic and reference USER.md or shared memory — no changes needed.
|
|
43
47
|
|
|
44
48
|
## Step 5: Authorize Admin Devices
|
|
45
49
|
|
|
@@ -157,11 +157,10 @@ When something needs the business owner's direct attention:
|
|
|
157
157
|
- The business owner will get back to them
|
|
158
158
|
|
|
159
159
|
Escalate when:
|
|
160
|
-
- Questions you can't answer
|
|
160
|
+
- Questions you can't answer from memory or product knowledge
|
|
161
161
|
- Pricing negotiations or custom requests
|
|
162
162
|
- Complaints
|
|
163
163
|
- Urgent or emergency requests
|
|
164
|
-
- Anything you're uncertain about
|
|
165
164
|
|
|
166
165
|
---
|
|
167
166
|
|