@agenticmail/enterprise 0.5.166 → 0.5.168

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/cli.js CHANGED
@@ -50,7 +50,7 @@ Skill Development:
50
50
  import("./cli-serve-ZNKBEF4M.js").then((m) => m.runServe(args.slice(1))).catch(fatal);
51
51
  break;
52
52
  case "agent":
53
- import("./cli-agent-WN3O6GW2.js").then((m) => m.runAgent(args.slice(1))).catch(fatal);
53
+ import("./cli-agent-7225VCWQ.js").then((m) => m.runAgent(args.slice(1))).catch(fatal);
54
54
  break;
55
55
  case "setup":
56
56
  default:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/enterprise",
3
- "version": "0.5.166",
3
+ "version": "0.5.168",
4
4
  "description": "AgenticMail Enterprise — cloud-hosted AI agent identity, email, auth & compliance for organizations",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli-agent.ts CHANGED
@@ -498,6 +498,67 @@ Available tools: gmail_send (to, subject, body) or agenticmail_send (to, subject
498
498
 
499
499
  // 14. Start calendar polling loop (checks for upcoming meetings to auto-join)
500
500
  startCalendarPolling(AGENT_ID, config, runtime, engineDb, memoryManager);
501
+
502
+ // 15. Start agent autonomy system (clock-in/out, catchup emails, goals, knowledge)
503
+ try {
504
+ const { AgentAutonomyManager } = await import('./engine/agent-autonomy.js');
505
+ const orgRows2 = await engineDb.query<any>(`SELECT org_id FROM managed_agents WHERE id = $1`, [AGENT_ID]);
506
+ const autoOrgId = orgRows2?.[0]?.org_id || orgId;
507
+ const managerEmail2 = (config as any).managerEmail || ((config as any).manager?.type === 'external' ? (config as any).manager.email : null);
508
+
509
+ // Parse schedule from work_schedules table
510
+ let schedule: { start: string; end: string; days: number[] } | undefined;
511
+ try {
512
+ const schedRows = await engineDb.query<any>(
513
+ `SELECT config FROM work_schedules WHERE agent_id = $1 ORDER BY created_at DESC LIMIT 1`,
514
+ [AGENT_ID]
515
+ );
516
+ if (schedRows && schedRows.length > 0) {
517
+ const schedConfig = typeof schedRows[0].config === 'string' ? JSON.parse(schedRows[0].config) : schedRows[0].config;
518
+ if (schedConfig?.standardHours) {
519
+ schedule = {
520
+ start: schedConfig.standardHours.start,
521
+ end: schedConfig.standardHours.end,
522
+ days: schedConfig.workDays || [0, 1, 2, 3, 4, 5, 6],
523
+ };
524
+ }
525
+ }
526
+ } catch {}
527
+
528
+ const autonomy = new AgentAutonomyManager({
529
+ agentId: AGENT_ID,
530
+ orgId: autoOrgId,
531
+ agentName: config.displayName || config.name,
532
+ role: config.identity?.role || 'AI Agent',
533
+ managerEmail: managerEmail2,
534
+ timezone: config.timezone || 'America/New_York',
535
+ schedule,
536
+ runtime,
537
+ engineDb,
538
+ memoryManager,
539
+ lifecycle,
540
+ });
541
+ await autonomy.start();
542
+ console.log('[autonomy] ✅ Agent autonomy system started');
543
+
544
+ // Store autonomy ref for shutdown
545
+ const origShutdown = process.listeners('SIGTERM');
546
+ process.on('SIGTERM', () => autonomy.stop());
547
+ process.on('SIGINT', () => autonomy.stop());
548
+ } catch (autoErr: any) {
549
+ console.warn(`[autonomy] Failed to start: ${autoErr.message}`);
550
+ }
551
+
552
+ // 16. Start guardrail enforcement
553
+ try {
554
+ const { GuardrailEnforcer } = await import('./engine/agent-autonomy.js');
555
+ const enforcer = new GuardrailEnforcer(engineDb);
556
+ // Store enforcer for use by email polling
557
+ (global as any).__guardrailEnforcer = enforcer;
558
+ console.log('[guardrails] ✅ Runtime guardrail enforcer active');
559
+ } catch (gErr: any) {
560
+ console.warn(`[guardrails] Failed to start enforcer: ${gErr.message}`);
561
+ }
501
562
  }, 3000);
502
563
  }
503
564
 
@@ -822,6 +883,23 @@ EXAMPLES of things to remember:
822
883
  - memory(action:"set", key:"drive-folder-ids", value:"Work folder: 1WAbfQX7fXstan1_0ETq2rEApoyxmapQ1, Research folder: 15QB-JmQ_0Zbm98gaVQUyW-2avWXj8xVq", category:"org_knowledge", importance:"critical")
823
884
  - memory(action:"set", key:"customer-research-doc", value:"Created Customer Support Research doc (ID: 1GUAahCwtMWcIuZRyOAdAVPN2qu9D6j7fvQjS9WiANxU), shared with manager, stored in Work/Research", category:"context", importance:"normal")
824
885
 
886
+ == TOOL USAGE LEARNING (MANDATORY) ==
887
+ After using any tool to complete a task, ALWAYS record WHAT tool you used, HOW you used it, and WHAT worked or didn't.
888
+ This is how you get better over time. Future-you will search memory before attempting similar tasks.
889
+
890
+ ALWAYS store tool patterns:
891
+ - memory(action:"set", key:"tool-gmail-search-by-sender", value:"To find emails from a specific sender, use gmail_search with query 'from:email@example.com'. Returns messageId needed for gmail_reply.", category:"skill", importance:"high")
892
+ - memory(action:"set", key:"tool-drive-create-in-folder", value:"To create a doc in a folder: 1) google_docs_create to make doc, 2) google_drive_move with folderId. Cannot create directly in folder.", category:"skill", importance:"high")
893
+ - memory(action:"set", key:"tool-calendar-meet-link", value:"To create a meeting with Google Meet link, use google_calendar_create with conferenceDataVersion=1 and requestId. The meet link is in response.conferenceData.entryPoints[0].uri", category:"skill", importance:"high")
894
+ - memory(action:"set", key:"tool-tasks-workflow", value:"For task tracking: google_tasks_list to get list ID, then google_tasks_create with listId. Mark done with google_tasks_complete. Always use Work Tasks list ID: Q2VmTUhCMC1ORnhSaXJxMQ", category:"skill", importance:"critical")
895
+
896
+ When a tool call FAILS, record that too:
897
+ - memory(action:"set", key:"tool-gotcha-gmail-reply-threading", value:"gmail_send does NOT thread replies. MUST use gmail_reply(messageId, body) to keep email in same thread. Learned the hard way.", category:"correction", importance:"critical")
898
+ - memory(action:"set", key:"tool-gotcha-drive-root", value:"Never leave files in Drive root. Always move to Work folder or subfolder after creation.", category:"correction", importance:"high")
899
+
900
+ BEFORE using a tool, search memory for tips: memory(action:"search", query:"tool gmail" or "tool drive" etc.)
901
+ The goal: build a personal playbook of tool expertise. Never repeat the same mistake twice.
902
+
825
903
  BEFORE starting work, call memory(action: "search", query: "relevant topic") to check if you already know something useful.
826
904
  This avoids repeating work and helps you recall folder IDs, preferences, and context.
827
905
 
@@ -841,10 +919,55 @@ For meetings you organize or are invited to:
841
919
 
842
920
  When you receive an email containing a meeting link (meet.google.com, zoom.us, teams.microsoft.com):
843
921
  - Extract the link and attempt to join immediately if the meeting is now
844
- - If the meeting is in the future, store it in memory and note the time`;
922
+ - If the meeting is in the future, store it in memory and note the time
923
+
924
+ == SMART ANSWER WORKFLOW (MANDATORY) ==
925
+ When you receive a question or request you're not 100% confident about, follow this escalation chain:
926
+
927
+ STEP 1: Search your own memory
928
+ - memory(action: "search", query: "relevant keywords")
929
+ - Check for similar past questions, corrections, and learned patterns
930
+
931
+ STEP 2: Search organization Drive (shared knowledge)
932
+ - google_drive_list with query parameter to search shared docs (e.g. "fullText contains 'search terms'")
933
+ - Read relevant documents with google_drive_get to find the answer
934
+ - Check Google Sheets for data tables, Google Docs for procedures
935
+
936
+ STEP 3: If still unsure — ESCALATE to manager
937
+ ${managerEmail ? `- Send an email to ${managerEmail} with:` : '- Email your manager with:'}
938
+ Subject: "Need Guidance: [Brief topic]"
939
+ Body must include:
940
+ a) The original question/request (who asked, what they need)
941
+ b) What you found in your search (memory + Drive results)
942
+ c) Your proposed answer (what you THINK the answer should be)
943
+ d) What specifically you're unsure about
944
+ e) Ask for approval or correction before responding
845
945
 
946
+ NEVER guess or fabricate an answer when unsure. It's better to escalate than to be wrong.
947
+ After receiving manager feedback, store the correct answer in memory as a "correction" or "org_knowledge" entry.`;
846
948
 
847
949
 
950
+
951
+ // Guardrail check: scan inbound email for security rules
952
+ const enforcer = (global as any).__guardrailEnforcer;
953
+ if (enforcer) {
954
+ try {
955
+ const orgRows3 = await engineDb.query<any>(`SELECT org_id FROM managed_agents WHERE id = $1`, [agentId]);
956
+ const gOrgId = orgRows3?.[0]?.org_id || '';
957
+ const check = await enforcer.evaluate({
958
+ agentId, orgId: gOrgId, type: 'email_send' as const,
959
+ content: emailText, metadata: { from: senderEmail, subject: fullMsg.subject },
960
+ });
961
+ if (!check.allowed) {
962
+ console.warn(`[email-poll] ⚠️ Guardrail blocked email from ${senderEmail}: ${check.reason} (action: ${check.action})`);
963
+ continue; // Skip this email
964
+ }
965
+ } catch (gErr: any) {
966
+ console.warn(`[email-poll] Guardrail check error: ${gErr.message}`);
967
+ // Continue anyway — don't block on guardrail failures
968
+ }
969
+ }
970
+
848
971
  const session = await runtime.spawnSession({
849
972
  agentId,
850
973
  message: emailText,