@audienti/cli 0.2.0-exora.18 → 0.2.0-exora.19

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/cli/audienti.mjs CHANGED
@@ -81,7 +81,7 @@ Discovery: prospects list|get ID|timeline ID [--limit N]|observation create|cita
81
81
  usage breakdown [--workspace ID] [--since month|7d|30d|90d] [--by tool|provider|model|caller|day] [--format json|csv]
82
82
  workspace usage summary|callers|calls [--after ID] [--caller user:ID|agent:ID|key:ID] [--status all|succeeded|failed|pending]|call ID [--workspace ID] (paid tool use, last 30 days, and single calls)
83
83
  intent list [--workspace ID] (the closed set of message labels: name, direction, event, channels, typed detail; output is JSON)
84
- intent record --person ID --evidence ID --label NAME --quote TEXT --reason TEXT [--confidence high|medium|low] [--request-id UUID] [--participation ID] [--workspace ID] (what a stored message means; get EVIDENCE from prospects conversation append|list; --file LABELS.json for several labels or a typed detail such as a stop result or a meeting time; every label is checked and a refusal says what to fix)
84
+ intent record --person ID --evidence ID --label NAME --quote TEXT --reason TEXT [--confidence high|medium|low] [--request-id UUID] [--participation ID] [--workspace ID] (what a stored message means; get EVIDENCE from prospects conversation append|list; --file LABELS.json for several labels or a typed detail such as a stop result or a meeting time; every label is checked and a refusal says what to fix; a message you sent that asks for a meeting takes --label meeting_requested on its outbound evidence)
85
85
  audit list [--workspace ID] [--since 7d] [--actor agent|person] [--category NAME] [--format json|csv]
86
86
  budgets set --workspace ID [--agent ID --cap N|none] [--new-agent-cap N|none] [--at-limit pause|ask] [--alert80 on|off] (alert80 covers Operator and email at 80%)
87
87
  Qualification: campaigns qualification submit --file INPUT.json
@@ -122,6 +122,7 @@ Tool names follow the commands: playbook_get for playbook show, playbook_draft_g
122
122
  Errors name the MCP tool to call next, not the command.`;
123
123
  // Example inputs for the commands that save prospects, so `--help` shows a working shape.
124
124
  const examples = {
125
+ 'prospects conversation append': { requestId: 'UUID', item: { source: { provider: 'email', accountRef: 'you@yourcompany.com', itemId: 'PROVIDER_MESSAGE_ID', threadId: null }, payload: { direction: 'outbound', conversationType: 'direct', occurredAt: '2026-11-06T14:00:00Z', subject: 'Ten minutes on late invoices?', body: 'Hi Jordan, could we find 20 minutes next week?', participants: null } } },
125
126
  'intent record': [{ label: 'stop', quote: 'please stop writing to me', reason: 'They ask us to stop.', result: { type: 'reply.stop', scope: 'person' } }],
126
127
  'prospects observation create': { requestId: 'UUID', kind: 'person', source: { provider: 'linkedin', url: 'https://www.linkedin.com/in/jane-doe' }, fields: { name: 'Jane Doe', title: 'VP Sales', imageUrl: 'https://media.licdn.com/dms/image/PHOTO_ID' }, provenance: { url: 'https://example.com/team/jane' }, observedAt: '2026-01-01T00:00:00Z', skill: { id: 'signal-prospect-research', version: '1' } },
127
128
  'prospects citation create': { requestId: 'UUID', source: { kind: 'prospect', id: 'PERSON_PROSPECT_ID' }, target: { kind: 'prospect', id: 'COMPANY_PROSPECT_ID' }, edgeType: 'works_at', roles: [{ roleId: 'role-1', title: 'VP Sales', current: true, observedAt: '2026-01-01T00:00:00Z' }] },
@@ -140,7 +141,7 @@ function commandHelp() {
140
141
  }
141
142
  console.log(shown.length ? shown.map(line => line.trim()).join('\n') : usage);
142
143
  const example = Object.entries(examples).find(([command]) => words.join(' ').startsWith(command) || (words.length > 0 && command.startsWith(words.join(' '))));
143
- if (example) console.log(`\nExample --file INPUT.json for ${example[0]}:\n${JSON.stringify(example[1], null, 1)}\n${example[0].startsWith('intent') ? 'Rules: the "Label a message with its words" section of the getting-started replies reference.' : 'Steps and rules: the "Save prospects and contacts" section of llms.txt.'}`);
144
+ if (example) console.log(`\nExample --file INPUT.json for ${example[0]}:\n${JSON.stringify(example[1], null, 1)}\n${example[0].startsWith('intent') ? `\nA message you sent that asks for a meeting (store it first with prospects conversation append, direction outbound):\naudienti intent record --person PERSON --evidence EVIDENCE --label meeting_requested --quote "find 20 minutes next week" --reason "We ask for a call next week."\nRules: the "Label a message with its words" and "Label a message you sent" sections of the getting-started replies reference.` : 'Steps and rules: the "Save prospects and contacts" section of llms.txt.'}`);
144
145
  }
145
146
 
146
147
  /** Says what is wrong with a command no handler took, instead of one message for every case. */
@@ -30,6 +30,6 @@ export const intentOperations = {
30
30
  labels: z.array(label).min(1),
31
31
  }).strict(),
32
32
  method: 'POST', path: a => `/workspaces/${a.workspaceId}/intents`, scoped: true, body: ({ workspaceId, ...rest }) => rest,
33
- description: 'Record what a message means: one to three labels, each with the quote that supports it and a plain reason. The message must already be stored as conversation evidence with its text. Every label is checked first and nothing is written if one fails: the name is known and fits the direction and channel, the quote is in the message, the reason is plain words, the labels fit together (stop, bounce and out_of_office stand alone), and the typed detail a stop, bounce, referral or booked meeting needs is present. A refusal names the field, the allowed values and the next step. The same requestId with the same body returns the first answer. The matching events land on the person\'s running campaigns, so the playbook rules act on them. Replies set records the same labels when you give it an intent block.',
33
+ description: 'Record what a message means: one to three labels, each with the quote that supports it and a plain reason. The message must already be stored as conversation evidence with its text. Every label is checked first and nothing is written if one fails: the name is known and fits the direction and channel, the quote is in the message, the reason is plain words, the labels fit together (stop, bounce and out_of_office stand alone), and the typed detail a stop, bounce, referral or booked meeting needs is present. A refusal names the field, the allowed values and the next step. The same requestId with the same body returns the first answer. The matching events land on the person\'s running campaigns, so the playbook rules act on them. Replies set records the same labels when you give it an intent block. A message you sent can be labeled too: store it first as outbound conversation evidence, then record meeting_requested when it asks for or offers a meeting. That puts the request on the meeting timeline and starts the meeting follow-ups without a reply.',
34
34
  },
35
35
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audienti/cli",
3
- "version": "0.2.0-exora.18",
3
+ "version": "0.2.0-exora.19",
4
4
  "description": "Audienti CLI and MCP client for app.audienti.com",
5
5
  "type": "module",
6
6
  "bin": {
@@ -116,6 +116,41 @@ values and the `next` step. The checks:
116
116
  `replies set` records the same labels. Add `"intent": {"quote": "...", "reason": "..."}` next to `classification`
117
117
  or `meetingState` and it runs the same checks and stores the words on the event. Without `intent` it works as before.
118
118
 
119
+ ## Label a message you sent
120
+
121
+ A message you sent can carry a label too. Today one fits: `meeting_requested`, for a message that asks for a
122
+ meeting or offers a time ("could we find 20 minutes next week?"). Without it Audienti does not know a meeting
123
+ was asked for, so the playbook's meeting wait cannot follow it up. With it the timeline shows the request, the
124
+ wait sends up to 3 follow-ups, and a request nobody answers is marked No answer. No reply is needed.
125
+
126
+ Do it after the send, in two calls. Store what you sent, then label it:
127
+
128
+ ```
129
+ audienti prospects conversation append PERSON --workspace ID --file ITEM.json
130
+ audienti intent record --person PERSON --evidence EVIDENCE \
131
+ --label meeting_requested --quote "find 20 minutes next week" --reason "We ask for a call next week."
132
+ ```
133
+
134
+ `ITEM.json` holds a new `requestId` and the sent message. Give it the text exactly as you sent it:
135
+
136
+ ```
137
+ { "requestId": "<uuid>",
138
+ "item": {
139
+ "source": { "provider": "email", "accountRef": "you@yourcompany.com", "itemId": "<the provider's message ID>", "threadId": null },
140
+ "payload": { "direction": "outbound", "conversationType": "direct", "occurredAt": "2026-11-06T14:00:00Z",
141
+ "subject": "Ten minutes on late invoices?", "body": "Hi Jordan, could we find 20 minutes next week?", "participants": null } } }
142
+ ```
143
+
144
+ The call returns `EVIDENCE`. If you stored the message already, to report the send (`account_evidence`) or as
145
+ the `responseEvidenceId` of an answer, use that same ID. The `quote` must be words from what you sent.
146
+ The same checks apply: a message with no stored text, a quote that is not in it, or a label that does not fit a sent message (`interested` fits a reply, not an ask) is refused and writes nothing.
147
+
148
+ - Label only a message that asks for or offers a meeting. A message that does not is not labeled.
149
+ - A follow-up that asks again needs no label: the request is already on the timeline, so a repeat writes nothing.
150
+ The same message cannot take the label twice (`already_recorded`).
151
+ - The label goes on the person's running campaign. A person runs in one campaign per workspace, so you need no option; `--participation ID` names the run if you want it explicit. The answer to `work execution send` or `report` carries that `participationId` when the send started a playbook step and the person still runs in the campaign run the send started, also when you repeat the call. A person who left and rejoined has a new run: a repeat of the old send names none. The label works without it.
152
+ - An answer to a reply that offers times is labeled the same way, with the evidence of the answer you sent.
153
+
119
154
  ## Stop, bounce and referral
120
155
 
121
156
  These three need no decision from the user. Classify the reply, report the typed
@@ -187,7 +222,8 @@ report it as a stop.
187
222
  A `work.execute` task with `action: send_reply` follows. Claim it, send the answer in
188
223
  the thread the prospect wrote in, report the result, then close the reply with status
189
224
  `handled`, outcome `response_recorded` and the sent message's evidence as
190
- `responseEvidenceId`.
225
+ `responseEvidenceId`. If your answer offers times for a meeting, label that sent message
226
+ `meeting_requested` with the same evidence ("Label a message you sent").
191
227
 
192
228
  ## When a meeting is booked
193
229
 
@@ -204,9 +240,11 @@ the thread the prospect wrote in, report the result, then close the reply with s
204
240
 
205
241
  ## Before a meeting is booked
206
242
 
207
- Record where an unbooked meeting stands with `"meetingState"` in a `replies set` result:
243
+ Record where an unbooked meeting stands. When the prospect writes about it, use `"meetingState"` in a
244
+ `replies set` result. When you ask for the meeting in a message you sent, label that message
245
+ `meeting_requested` (see "Label a message you sent"):
208
246
 
209
- - `requested`: a time was asked for or offered.
247
+ - `requested`: a time was asked for or offered, by them or by you.
210
248
  - `accepted`: they agreed, and no time is fixed yet.
211
249
  - `declined`: they said no to the meeting. A plain no is not a request to stop; classify the
212
250
  reply on its own.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "repository": "https://github.com/omalab/exora",
3
- "sourceCommit": "4cab4a5e992c5dea08547078bee1839d951a6d22",
3
+ "sourceCommit": "a6ae26f0d63d6ad78f58157203675f491cb6a393",
4
4
  "files": {
5
5
  "LICENSE": "220f297cfcd5c38eb64e6b4b4a77cab4ebc7f4686d4d99c6260a475d02ca11e5",
6
6
  "README.md": "7ff32cc8ac89dd54b64d7b39c0b41b1f37e154b7ea10ad5a7bceefc3df77d87f",
@@ -16,7 +16,7 @@
16
16
  "cli/attachments.mjs": "2fee6b4abbf82da9847d4a927a3d4d3ca947a198a903a78927596a2ea858cbf4",
17
17
  "cli/audience-operations.mjs": "133b72dc6b9e3a6b4f173ce28f1524163f9c7b049505b885115f83b9e4af7170",
18
18
  "cli/audiences.mjs": "3c377346efc1a8bdde432a16c2d19a3f51f34f3333d344d3a2bfa94c188a017d",
19
- "cli/audienti.mjs": "e9789a8fc1700fa82c2fafba2147d64a0f8818052d4728690aff503c0434233c",
19
+ "cli/audienti.mjs": "c910e05bc15312132b5790e783c0ba5fdfb959a3ffcee7e22c3caaf07e206784",
20
20
  "cli/audit-operations.mjs": "afaf87d592a1e5f6bff2a8649a6a64a8f471950b7d99e98995d9205aa5910398",
21
21
  "cli/audit.mjs": "a7becaed67c58b063e668b5e66844b6dc15c11a63b428faa171b542ad922c001",
22
22
  "cli/budget-operations.mjs": "d74916551ef393e29734c6e13cf9021251e0ed126eeaa529e18cf2332146e1e0",
@@ -36,7 +36,7 @@
36
36
  "cli/guardrails.mjs": "e8b9c0a19956a9eab84475d3c56a4b6c77baf7ed9a55e8686d660ef1ad562aa8",
37
37
  "cli/hand-task-operations.mjs": "473473fe95324c8c8733e037feab5ac468c07b0658fabd739cfd7d400a7faa83",
38
38
  "cli/hand-tasks.mjs": "2c895cf6b30c594a7e27cc4ec4b7eddeb39f941cd195b9255c6e0d6b4a56371f",
39
- "cli/intent-operations.mjs": "104e883319b4e9c2fb43de373fcf9d5df537871995a0b81b4ee86fa206ba6707",
39
+ "cli/intent-operations.mjs": "97b08e7474cf0fd8201650f08fa5ca5a2be2b0ddf5ea2079eb644e21aa2a0153",
40
40
  "cli/intent.mjs": "db0ccb85977fca26f865970dacd0538e81b070d7c0ec078f38358f33c458a96a",
41
41
  "cli/json-file.mjs": "96431b18215834c2531f5901e2526875c634dd2e85a9465fcffc937fbec52150",
42
42
  "cli/kv-operations.mjs": "505d79d0d535d3441883f8a37817c30c73367216a35dddb07181f0f0e799df79",
@@ -84,7 +84,7 @@
84
84
  "cli/work-operations.mjs": "8b3a84ca15e8e4ad79ef92ced4c5adaffd5129f630e3bfc2c74a844a90867600",
85
85
  "cli/work.mjs": "751107ecc3de5a6be9db4a068cddc41f3ad8e77c87e59686eaf522862caf9e9f",
86
86
  "cli/workspaces.mjs": "eebe2c4bfc6ddedb2fb0dd551d5fa348eeda2fdf2105babd514b29a97f4d6225",
87
- "package.json": "95dfaba2962c0a73f054289dfa3cdcad7e667dc932ba7d0fcfa35517e7ad1513",
87
+ "package.json": "706c6a417391f446280be9976f31adc46e36f70aca03ec9d4eb9b8f82ef9964a",
88
88
  "skills/agent-rooms/SKILL.md": "08f917ff85fee1d23499a4499056ce845b39ce6727029b104819dad41ee87cc2",
89
89
  "skills/agent-rooms/references/commands.md": "ef5afa5543ca9da967a147f638774647998ea1c1a2a821959f3bf87d54c292bd",
90
90
  "skills/audienti/SKILL.md": "8f2124065bfc3a005b44e194e7dcce9bbf14062ab332e7db66d441eeccb518ed",
@@ -100,7 +100,7 @@
100
100
  "skills/getting-started/references/capabilities.md": "982e3583a47ba4ac832efae2f6af3a4d8c0c18cace159c76b2a4ad1a8d8e910e",
101
101
  "skills/getting-started/references/mailbox-check.md": "113574bb5a573125620dcde4e65ebf44164f7b0727cc936fb41234f5d57bba73",
102
102
  "skills/getting-started/references/outcome-checks.md": "094d09d231b38d4935aa9eb8ac089e46ba8e698489852fa97040e6b5eac77a9b",
103
- "skills/getting-started/references/replies.md": "d085b7353f13d70a1b0333d851fe573fd2c99e6bb57923cf8717982d77a0504b",
103
+ "skills/getting-started/references/replies.md": "4a89c2310a7f4b9d3f01dee44557bd71bc63e9ccba84500f6d8f7291dd99c1b0",
104
104
  "skills/getting-started/references/reply-checks.md": "85fe692ad6b7bc73e204de313b27d225be3da1a0af71e8e7bb9945ae511a0dc3",
105
105
  "skills/playbook-design/SKILL.md": "eec38bb7cd1586e11c6c27cccf328c1731d404f0767bd1df0c3ac8273495cb50",
106
106
  "skills/playbook-design/references/fields.md": "7d4a22451c3b77bb21a76d211d25a44b84a1bc46cc6524472ed121e77d2866aa"