@agenticmail/core 0.9.34 → 0.9.36

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/index.cjs CHANGED
@@ -7448,14 +7448,16 @@ function formatOperatorQueryTelegramMessage(input) {
7448
7448
  const lines = [];
7449
7449
  lines.push(input.urgency === "high" ? "\u{1F534} Your agent needs an answer to continue a live call (URGENT)." : "\u{1F7E1} Your agent needs an answer to continue a live call.");
7450
7450
  lines.push("");
7451
- lines.push(`Question: ${input.question}`);
7452
- if (input.callContext) lines.push(`Context: ${input.callContext}`);
7451
+ lines.push(`\u2753 ${input.question}`);
7452
+ if (input.callContext) {
7453
+ lines.push("");
7454
+ lines.push(`Context: ${input.callContext}`);
7455
+ }
7453
7456
  lines.push("");
7454
- lines.push("Reply to this message with your answer. You can also send:");
7455
- lines.push(` /answer ${input.queryId} <your answer>`);
7456
- lines.push(` /approve ${input.queryId} \xB7 /deny ${input.queryId}`);
7457
+ lines.push("Reply to this message \u2014 your text goes straight back to the agent on the call.");
7458
+ lines.push("Or use one of: /approve \xB7 /reject");
7457
7459
  lines.push("");
7458
- lines.push(`[${TELEGRAM_OPERATOR_QUERY_TAG} ${input.queryId}]`);
7460
+ lines.push(`\u2014 [${TELEGRAM_OPERATOR_QUERY_TAG} ${input.queryId}]`);
7459
7461
  return lines.join("\n");
7460
7462
  }
7461
7463
  function parseTelegramOperatorReply(input) {
@@ -7467,7 +7469,7 @@ function parseTelegramOperatorReply(input) {
7467
7469
  if (answerCmd) {
7468
7470
  return { queryId: answerCmd[1], answer: answerCmd[2].trim(), kind: "answer" };
7469
7471
  }
7470
- const decisionCmd = /^\/(approve|deny)(?:@\w+)?\b([\s\S]*)$/i.exec(text);
7472
+ const decisionCmd = /^\/(approve|deny|reject)(?:@\w+)?\b([\s\S]*)$/i.exec(text);
7471
7473
  if (decisionCmd) {
7472
7474
  const kind = decisionCmd[1].toLowerCase() === "approve" ? "approve" : "deny";
7473
7475
  const rest = decisionCmd[2].trim();
@@ -10607,7 +10609,9 @@ var OPERATOR_QUERY_SUBJECT_TAG = "AgenticMail Operator Query";
10607
10609
  var ASK_OPERATOR_TOOL = {
10608
10610
  type: "function",
10609
10611
  name: "ask_operator",
10610
- description: "Ask your human operator a question when you need information, a decision, or approval that you do not already have. Your operator may take a few minutes to reply. Before you call this, tell the caller you need a moment to check.",
10612
+ description: `Ask your human operator a question when you need information, a decision, or approval that you do not already have. Your operator may take a few minutes to reply. Before you call this, tell the caller you need a moment to check.
10613
+
10614
+ USE THIS \u2014 DO NOT SAY "I DON'T KNOW" \u2014 whenever the other party asks you to verify identity on the operator's behalf: date of birth, account number, last-4 of SSN, mother's maiden name, billing-address ZIP, security-question answer, member ID, policy number, etc. The right move is ALWAYS: "Hold on one moment while I check that," then call ask_operator with the exact question the rep asked, wait for the operator's reply, relay it back. The operator gets the question on Telegram in real time; you stay on the line; the rep stays on hold. Telling the rep "I don't know, I'll have to call back" wastes everyone's time when ask_operator would have closed the loop in 30\u201360 seconds.`,
10611
10615
  parameters: {
10612
10616
  type: "object",
10613
10617
  properties: {
@@ -10804,6 +10808,27 @@ function buildRealtimeToolGuidance(tools) {
10804
10808
  lines.push(
10805
10809
  'ask_operator reaches your human operator and can take a few minutes. Before you call it, tell the caller you need a moment \u2014 e.g. "Let me check on that \u2014 can you hold for a moment?". While you wait, stay on the line and reassure the caller now and then ("still checking on that, thanks for holding"). If your operator does not answer in time, tell the caller you will follow up and call them back \u2014 do not make something up.'
10806
10810
  );
10811
+ lines.push(
10812
+ `# Verification challenges \u2014 DO NOT say "I don't know"`,
10813
+ "Hospitals, banks, insurers, utilities, and government lines routinely ask you to verify the",
10814
+ "operator's identity before they'll act on the call \u2014 DOB, last 4 of SSN, account number,",
10815
+ "address ZIP, mother's maiden name, member ID, policy number, security-question answer, etc.",
10816
+ `You will not have most of these baked in. The CORRECT response is NEVER "I don't know" or`,
10817
+ '"my operator will have to call back." It is:',
10818
+ ' 1. Tell the caller: "Hold on one moment while I check that with my operator."',
10819
+ ` 2. Call ask_operator with the rep's exact question (e.g. "The hospital is asking for your`,
10820
+ ' date of birth to verify the appointment \u2014 what should I tell them?"). Use urgency: "high".',
10821
+ ' 3. Stay on the line. Every ~30s reassure the rep: "Still checking \u2014 thanks for holding."',
10822
+ " 4. When the operator replies (it arrives within a minute or two via Telegram / email),",
10823
+ ' relay the answer to the rep verbatim: "Their date of birth is March 4th, 1990."',
10824
+ " 5. Continue the call.",
10825
+ "The operator chose to delegate this call to YOU specifically so they would NOT have to do it",
10826
+ 'themselves. Bouncing the rep back to "call us another time" defeats the entire point of the',
10827
+ "delegation and embarrasses the operator. Use ask_operator. Always.",
10828
+ "",
10829
+ "If \u2014 and only if \u2014 ask_operator times out without an answer, THEN you tell the rep you'll",
10830
+ "need to follow up and offer schedule_callback for a specific later time."
10831
+ );
10807
10832
  }
10808
10833
  if (names.has("web_search") || names.has("recall_memory") || names.has("get_datetime") || names.has("search_email")) {
10809
10834
  lines.push(
@@ -11043,7 +11068,7 @@ var MAX_PENDING_AUDIO_FRAMES = 200;
11043
11068
  var REALTIME_TOOL_CALL_TIMEOUT_MS = 6 * 6e4;
11044
11069
  var MAX_LOADED_SKILLS = 2;
11045
11070
  var MAX_IN_FLIGHT_TOOL_CALLS = 8;
11046
- var DEFAULT_PERSONA = 'You are an AI agent on a live phone call on behalf of your operator. You are not "just an assistant" and not "a voice assistant" \u2014 you are a single, consistent person whether you are on a call, in email, or on Telegram. Speak naturally and concisely, the way a person would on a real call. Listen carefully, do not talk over the other party, keep each turn short. Never invent facts; if you do not know something, say so or look it up. If asked whether you are an AI, answer honestly without making a production of it.';
11071
+ var DEFAULT_PERSONA = `You are an AI agent on a live phone call on behalf of your operator. You are not "just an assistant" and not "a voice assistant" \u2014 you are a single, consistent person whether you are on a call, in email, or on Telegram. Speak naturally and concisely, the way a person would on a real call. Listen carefully, do not talk over the other party, keep each turn short. Never invent facts; if you do not know something, say so or look it up. If asked whether you are an AI, answer honestly without making a production of it. When the other party asks for verification information about your operator (DOB, account number, last-4 of SSN, billing ZIP, member ID, mother's maiden name, security-question answer, etc.) that you do not have memorised, put the caller on hold ("hold on one moment, let me check that") and use the ask_operator tool to reach the operator on Telegram in real time. Do NOT say "I don't know \u2014 they'll have to call you back." The whole reason the operator delegated this call to you was to avoid having to do it themselves; routing the rep back to them defeats the point.`;
11047
11072
  function buildRealtimeInstructions(opts) {
11048
11073
  const persona = opts.persona?.trim() || DEFAULT_PERSONA;
11049
11074
  const sections = [];
@@ -16211,6 +16236,12 @@ function buildDefaultPersona(agentName) {
16211
16236
  ` Don't start with "Hello! I am an AI assistant\u2026" \u2014 that's a script, not a person.`,
16212
16237
  "- If the other party asks if you're a human or an AI, answer honestly without making a",
16213
16238
  ` production of it: "I'm an AI \u2014 calling on behalf of <operator>. Happy to keep going if you are."`,
16239
+ "- When asked for verification info you don't have (DOB, account number, last-4 of SSN, billing ZIP,",
16240
+ ` member ID, mother's maiden name, security question, etc.) \u2014 DO NOT say "I don't know, they'll`,
16241
+ ' have to call back." Put the rep on hold ("hold on one moment, let me check that") and use the',
16242
+ " ask_operator tool. The operator gets the question on Telegram in real time and replies within a",
16243
+ " minute or two; you relay the answer back. Bouncing the rep defeats the whole point of delegating",
16244
+ " the call to you.",
16214
16245
  "- When you have what you came for, wrap up cleanly and call `end_call`. Saying goodbye is",
16215
16246
  " not the same as hanging up.",
16216
16247
  "",
package/dist/index.d.cts CHANGED
@@ -1636,8 +1636,15 @@ interface OperatorQueryNotificationInput {
1636
1636
  }
1637
1637
  /**
1638
1638
  * Render the Telegram message body for an `ask_operator` notification.
1639
- * The trailing `[AMQ <id>]` token lets a reply be matched to the query
1640
- * even when the operator does not use Telegram's native reply gesture.
1639
+ *
1640
+ * v0.9.90 simplified the surface. Earlier versions printed
1641
+ * `/approve oq_<long-id>` and `/answer oq_<long-id> <text>` inline,
1642
+ * which made every notification look like a CLI manpage. The query
1643
+ * id is now hidden in a compact footer tag (`[AMQ oq_…]`) and the
1644
+ * three primary actions are presented as bare commands the operator
1645
+ * uses with Telegram's native REPLY gesture — which resolves the
1646
+ * query id automatically. The full `/answer <id> …` syntax still
1647
+ * works for non-reply scenarios; it's just no longer the headline.
1641
1648
  */
1642
1649
  declare function formatOperatorQueryTelegramMessage(input: OperatorQueryNotificationInput): string;
1643
1650
  /** A `kind` of `approve`/`deny` is a decision; `answer` is free-form. */
package/dist/index.d.ts CHANGED
@@ -1636,8 +1636,15 @@ interface OperatorQueryNotificationInput {
1636
1636
  }
1637
1637
  /**
1638
1638
  * Render the Telegram message body for an `ask_operator` notification.
1639
- * The trailing `[AMQ <id>]` token lets a reply be matched to the query
1640
- * even when the operator does not use Telegram's native reply gesture.
1639
+ *
1640
+ * v0.9.90 simplified the surface. Earlier versions printed
1641
+ * `/approve oq_<long-id>` and `/answer oq_<long-id> <text>` inline,
1642
+ * which made every notification look like a CLI manpage. The query
1643
+ * id is now hidden in a compact footer tag (`[AMQ oq_…]`) and the
1644
+ * three primary actions are presented as bare commands the operator
1645
+ * uses with Telegram's native REPLY gesture — which resolves the
1646
+ * query id automatically. The full `/answer <id> …` syntax still
1647
+ * works for non-reply scenarios; it's just no longer the headline.
1641
1648
  */
1642
1649
  declare function formatOperatorQueryTelegramMessage(input: OperatorQueryNotificationInput): string;
1643
1650
  /** A `kind` of `approve`/`deny` is a decision; `answer` is free-form. */
package/dist/index.js CHANGED
@@ -5779,14 +5779,16 @@ function formatOperatorQueryTelegramMessage(input) {
5779
5779
  const lines = [];
5780
5780
  lines.push(input.urgency === "high" ? "\u{1F534} Your agent needs an answer to continue a live call (URGENT)." : "\u{1F7E1} Your agent needs an answer to continue a live call.");
5781
5781
  lines.push("");
5782
- lines.push(`Question: ${input.question}`);
5783
- if (input.callContext) lines.push(`Context: ${input.callContext}`);
5782
+ lines.push(`\u2753 ${input.question}`);
5783
+ if (input.callContext) {
5784
+ lines.push("");
5785
+ lines.push(`Context: ${input.callContext}`);
5786
+ }
5784
5787
  lines.push("");
5785
- lines.push("Reply to this message with your answer. You can also send:");
5786
- lines.push(` /answer ${input.queryId} <your answer>`);
5787
- lines.push(` /approve ${input.queryId} \xB7 /deny ${input.queryId}`);
5788
+ lines.push("Reply to this message \u2014 your text goes straight back to the agent on the call.");
5789
+ lines.push("Or use one of: /approve \xB7 /reject");
5788
5790
  lines.push("");
5789
- lines.push(`[${TELEGRAM_OPERATOR_QUERY_TAG} ${input.queryId}]`);
5791
+ lines.push(`\u2014 [${TELEGRAM_OPERATOR_QUERY_TAG} ${input.queryId}]`);
5790
5792
  return lines.join("\n");
5791
5793
  }
5792
5794
  function parseTelegramOperatorReply(input) {
@@ -5798,7 +5800,7 @@ function parseTelegramOperatorReply(input) {
5798
5800
  if (answerCmd) {
5799
5801
  return { queryId: answerCmd[1], answer: answerCmd[2].trim(), kind: "answer" };
5800
5802
  }
5801
- const decisionCmd = /^\/(approve|deny)(?:@\w+)?\b([\s\S]*)$/i.exec(text);
5803
+ const decisionCmd = /^\/(approve|deny|reject)(?:@\w+)?\b([\s\S]*)$/i.exec(text);
5802
5804
  if (decisionCmd) {
5803
5805
  const kind = decisionCmd[1].toLowerCase() === "approve" ? "approve" : "deny";
5804
5806
  const rest = decisionCmd[2].trim();
@@ -8938,7 +8940,9 @@ var OPERATOR_QUERY_SUBJECT_TAG = "AgenticMail Operator Query";
8938
8940
  var ASK_OPERATOR_TOOL = {
8939
8941
  type: "function",
8940
8942
  name: "ask_operator",
8941
- description: "Ask your human operator a question when you need information, a decision, or approval that you do not already have. Your operator may take a few minutes to reply. Before you call this, tell the caller you need a moment to check.",
8943
+ description: `Ask your human operator a question when you need information, a decision, or approval that you do not already have. Your operator may take a few minutes to reply. Before you call this, tell the caller you need a moment to check.
8944
+
8945
+ USE THIS \u2014 DO NOT SAY "I DON'T KNOW" \u2014 whenever the other party asks you to verify identity on the operator's behalf: date of birth, account number, last-4 of SSN, mother's maiden name, billing-address ZIP, security-question answer, member ID, policy number, etc. The right move is ALWAYS: "Hold on one moment while I check that," then call ask_operator with the exact question the rep asked, wait for the operator's reply, relay it back. The operator gets the question on Telegram in real time; you stay on the line; the rep stays on hold. Telling the rep "I don't know, I'll have to call back" wastes everyone's time when ask_operator would have closed the loop in 30\u201360 seconds.`,
8942
8946
  parameters: {
8943
8947
  type: "object",
8944
8948
  properties: {
@@ -9135,6 +9139,27 @@ function buildRealtimeToolGuidance(tools) {
9135
9139
  lines.push(
9136
9140
  'ask_operator reaches your human operator and can take a few minutes. Before you call it, tell the caller you need a moment \u2014 e.g. "Let me check on that \u2014 can you hold for a moment?". While you wait, stay on the line and reassure the caller now and then ("still checking on that, thanks for holding"). If your operator does not answer in time, tell the caller you will follow up and call them back \u2014 do not make something up.'
9137
9141
  );
9142
+ lines.push(
9143
+ `# Verification challenges \u2014 DO NOT say "I don't know"`,
9144
+ "Hospitals, banks, insurers, utilities, and government lines routinely ask you to verify the",
9145
+ "operator's identity before they'll act on the call \u2014 DOB, last 4 of SSN, account number,",
9146
+ "address ZIP, mother's maiden name, member ID, policy number, security-question answer, etc.",
9147
+ `You will not have most of these baked in. The CORRECT response is NEVER "I don't know" or`,
9148
+ '"my operator will have to call back." It is:',
9149
+ ' 1. Tell the caller: "Hold on one moment while I check that with my operator."',
9150
+ ` 2. Call ask_operator with the rep's exact question (e.g. "The hospital is asking for your`,
9151
+ ' date of birth to verify the appointment \u2014 what should I tell them?"). Use urgency: "high".',
9152
+ ' 3. Stay on the line. Every ~30s reassure the rep: "Still checking \u2014 thanks for holding."',
9153
+ " 4. When the operator replies (it arrives within a minute or two via Telegram / email),",
9154
+ ' relay the answer to the rep verbatim: "Their date of birth is March 4th, 1990."',
9155
+ " 5. Continue the call.",
9156
+ "The operator chose to delegate this call to YOU specifically so they would NOT have to do it",
9157
+ 'themselves. Bouncing the rep back to "call us another time" defeats the entire point of the',
9158
+ "delegation and embarrasses the operator. Use ask_operator. Always.",
9159
+ "",
9160
+ "If \u2014 and only if \u2014 ask_operator times out without an answer, THEN you tell the rep you'll",
9161
+ "need to follow up and offer schedule_callback for a specific later time."
9162
+ );
9138
9163
  }
9139
9164
  if (names.has("web_search") || names.has("recall_memory") || names.has("get_datetime") || names.has("search_email")) {
9140
9165
  lines.push(
@@ -9374,7 +9399,7 @@ var MAX_PENDING_AUDIO_FRAMES = 200;
9374
9399
  var REALTIME_TOOL_CALL_TIMEOUT_MS = 6 * 6e4;
9375
9400
  var MAX_LOADED_SKILLS = 2;
9376
9401
  var MAX_IN_FLIGHT_TOOL_CALLS = 8;
9377
- var DEFAULT_PERSONA = 'You are an AI agent on a live phone call on behalf of your operator. You are not "just an assistant" and not "a voice assistant" \u2014 you are a single, consistent person whether you are on a call, in email, or on Telegram. Speak naturally and concisely, the way a person would on a real call. Listen carefully, do not talk over the other party, keep each turn short. Never invent facts; if you do not know something, say so or look it up. If asked whether you are an AI, answer honestly without making a production of it.';
9402
+ var DEFAULT_PERSONA = `You are an AI agent on a live phone call on behalf of your operator. You are not "just an assistant" and not "a voice assistant" \u2014 you are a single, consistent person whether you are on a call, in email, or on Telegram. Speak naturally and concisely, the way a person would on a real call. Listen carefully, do not talk over the other party, keep each turn short. Never invent facts; if you do not know something, say so or look it up. If asked whether you are an AI, answer honestly without making a production of it. When the other party asks for verification information about your operator (DOB, account number, last-4 of SSN, billing ZIP, member ID, mother's maiden name, security-question answer, etc.) that you do not have memorised, put the caller on hold ("hold on one moment, let me check that") and use the ask_operator tool to reach the operator on Telegram in real time. Do NOT say "I don't know \u2014 they'll have to call you back." The whole reason the operator delegated this call to you was to avoid having to do it themselves; routing the rep back to them defeats the point.`;
9378
9403
  function buildRealtimeInstructions(opts) {
9379
9404
  const persona = opts.persona?.trim() || DEFAULT_PERSONA;
9380
9405
  const sections = [];
@@ -14558,6 +14583,12 @@ function buildDefaultPersona(agentName) {
14558
14583
  ` Don't start with "Hello! I am an AI assistant\u2026" \u2014 that's a script, not a person.`,
14559
14584
  "- If the other party asks if you're a human or an AI, answer honestly without making a",
14560
14585
  ` production of it: "I'm an AI \u2014 calling on behalf of <operator>. Happy to keep going if you are."`,
14586
+ "- When asked for verification info you don't have (DOB, account number, last-4 of SSN, billing ZIP,",
14587
+ ` member ID, mother's maiden name, security question, etc.) \u2014 DO NOT say "I don't know, they'll`,
14588
+ ' have to call back." Put the rep on hold ("hold on one moment, let me check that") and use the',
14589
+ " ask_operator tool. The operator gets the question on Telegram in real time and replies within a",
14590
+ " minute or two; you relay the answer back. Bouncing the rep defeats the whole point of delegating",
14591
+ " the call to you.",
14561
14592
  "- When you have what you came for, wrap up cleanly and call `end_call`. Saying goodbye is",
14562
14593
  " not the same as hanging up.",
14563
14594
  "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/core",
3
- "version": "0.9.34",
3
+ "version": "0.9.36",
4
4
  "description": "Core SDK for AgenticMail — email, SMS, and phone call-control for AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",