@agenticmail/enterprise 0.5.50 → 0.5.52

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.
@@ -0,0 +1,459 @@
1
+ /**
2
+ * AgenticMail Agent Tools — Enterprise Native
3
+ *
4
+ * These tools give enterprise agents email capabilities by calling
5
+ * the org's email provider (Microsoft Graph / Gmail API) directly.
6
+ * No separate AgenticMail server needed — agents authenticate via
7
+ * the org's OAuth/SSO identity.
8
+ *
9
+ * Architecture:
10
+ * Agent tool call
11
+ * → AgenticMailManager.getProvider(agentId)
12
+ * → IEmailProvider (MS Graph / Gmail / IMAP)
13
+ * → Org mailbox
14
+ */
15
+
16
+ import type { AnyAgentTool, ToolCreationOptions, ToolParameterSchema } from '../types.js';
17
+ import { jsonResult, errorResult } from '../common.js';
18
+ import type { IEmailProvider, SendEmailOptions, SearchCriteria, AgentMessage, AgentTask } from '../../agenticmail/types.js';
19
+
20
+ /** Manager interface — we only need getProvider() */
21
+ export interface AgenticMailManagerRef {
22
+ getProvider(agentId: string): IEmailProvider;
23
+ getIdentity?(agentId: string): { email: string; name: string } | undefined;
24
+ /** Inter-agent messaging (if available) */
25
+ sendAgentMessage?(msg: Omit<AgentMessage, 'id' | 'createdAt' | 'read'>): Promise<AgentMessage>;
26
+ listAgentMessages?(agentId: string): Promise<AgentMessage[]>;
27
+ /** Task management (if available) */
28
+ createTask?(task: Omit<AgentTask, 'id' | 'createdAt' | 'updatedAt'>): Promise<AgentTask>;
29
+ listTasks?(agentId: string, direction?: 'incoming' | 'outgoing'): Promise<AgentTask[]>;
30
+ claimTask?(taskId: string): Promise<AgentTask>;
31
+ completeTask?(taskId: string, result: any): Promise<AgentTask>;
32
+ }
33
+
34
+ export interface AgenticMailToolsConfig {
35
+ /** The AgenticMailManager instance */
36
+ manager: AgenticMailManagerRef;
37
+ /** The agent ID these tools are for */
38
+ agentId: string;
39
+ }
40
+
41
+ /**
42
+ * Create all AgenticMail tools backed by the org's email provider.
43
+ * Tools operate on the agent's mailbox via OAuth — no API keys needed.
44
+ */
45
+ export function createAgenticMailTools(
46
+ config: AgenticMailToolsConfig,
47
+ options?: ToolCreationOptions,
48
+ ): AnyAgentTool[] {
49
+ const { manager, agentId } = config;
50
+ const tools: AnyAgentTool[] = [];
51
+
52
+ // ─── Helpers ──────────────────────────────────────────────────────
53
+
54
+ function getProvider(): IEmailProvider {
55
+ return manager.getProvider(agentId);
56
+ }
57
+
58
+ function p(props: Record<string, any>, required?: string[]): ToolParameterSchema {
59
+ return { type: 'object', properties: props, required };
60
+ }
61
+
62
+ function defTool(
63
+ name: string,
64
+ label: string,
65
+ description: string,
66
+ params: ToolParameterSchema,
67
+ risk: 'low' | 'medium' | 'high' | 'critical',
68
+ handler: (args: Record<string, unknown>) => Promise<any>,
69
+ ): void {
70
+ tools.push({
71
+ name,
72
+ label,
73
+ description,
74
+ category: 'utility',
75
+ risk,
76
+ parameters: params,
77
+ execute: async (_toolCallId, args) => {
78
+ try {
79
+ const result = await handler(args as Record<string, unknown>);
80
+ return jsonResult(result ?? { success: true });
81
+ } catch (err: any) {
82
+ return errorResult(err.message || String(err));
83
+ }
84
+ },
85
+ });
86
+ }
87
+
88
+ // ─── Email Core ───────────────────────────────────────────────────
89
+
90
+ defTool('agenticmail_send', 'Send Email',
91
+ 'Send an email from your org mailbox.',
92
+ p({
93
+ to: { type: 'string', description: 'Recipient email' },
94
+ subject: { type: 'string', description: 'Email subject' },
95
+ text: { type: 'string', description: 'Plain text body' },
96
+ html: { type: 'string', description: 'HTML body' },
97
+ cc: { type: 'string', description: 'CC recipients' },
98
+ bcc: { type: 'string', description: 'BCC recipients' },
99
+ replyTo: { type: 'string', description: 'Reply-to address' },
100
+ inReplyTo: { type: 'string', description: 'Message-ID to reply to' },
101
+ references: { type: 'array', description: 'Message-IDs for threading' },
102
+ }, ['to', 'subject']),
103
+ 'high',
104
+ async (args) => {
105
+ const provider = getProvider();
106
+ const opts: SendEmailOptions = {
107
+ to: String(args.to),
108
+ subject: String(args.subject),
109
+ body: String(args.text || ''),
110
+ html: args.html ? String(args.html) : undefined,
111
+ cc: args.cc ? String(args.cc) : undefined,
112
+ bcc: args.bcc ? String(args.bcc) : undefined,
113
+ replyTo: args.replyTo ? String(args.replyTo) : undefined,
114
+ inReplyTo: args.inReplyTo ? String(args.inReplyTo) : undefined,
115
+ references: args.references as string[] | undefined,
116
+ };
117
+ return provider.send(opts);
118
+ },
119
+ );
120
+
121
+ defTool('agenticmail_reply', 'Reply to Email',
122
+ 'Reply to an email by UID.',
123
+ p({
124
+ uid: { type: 'string', description: 'Email UID to reply to' },
125
+ text: { type: 'string', description: 'Reply text' },
126
+ replyAll: { type: 'boolean', description: 'Reply to all recipients' },
127
+ }, ['uid', 'text']),
128
+ 'high',
129
+ async (args) => {
130
+ const provider = getProvider();
131
+ return provider.reply(String(args.uid), String(args.text), !!args.replyAll);
132
+ },
133
+ );
134
+
135
+ defTool('agenticmail_forward', 'Forward Email',
136
+ 'Forward an email to another recipient.',
137
+ p({
138
+ uid: { type: 'string', description: 'Email UID to forward' },
139
+ to: { type: 'string', description: 'Recipient to forward to' },
140
+ text: { type: 'string', description: 'Additional message' },
141
+ }, ['uid', 'to']),
142
+ 'high',
143
+ async (args) => {
144
+ const provider = getProvider();
145
+ return provider.forward(String(args.uid), String(args.to), args.text ? String(args.text) : undefined);
146
+ },
147
+ );
148
+
149
+ defTool('agenticmail_inbox', 'List Inbox',
150
+ 'List recent emails in the inbox.',
151
+ p({
152
+ limit: { type: 'number', description: 'Max messages (default 20)' },
153
+ offset: { type: 'number', description: 'Skip messages (default 0)' },
154
+ }),
155
+ 'low',
156
+ async (args) => {
157
+ const provider = getProvider();
158
+ return provider.listMessages('INBOX', {
159
+ limit: args.limit ? Number(args.limit) : 20,
160
+ offset: args.offset ? Number(args.offset) : 0,
161
+ });
162
+ },
163
+ );
164
+
165
+ defTool('agenticmail_read', 'Read Email',
166
+ 'Read a specific email by UID.',
167
+ p({
168
+ uid: { type: 'string', description: 'Email UID' },
169
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
170
+ }, ['uid']),
171
+ 'low',
172
+ async (args) => {
173
+ const provider = getProvider();
174
+ return provider.readMessage(String(args.uid), args.folder ? String(args.folder) : undefined);
175
+ },
176
+ );
177
+
178
+ defTool('agenticmail_search', 'Search Emails',
179
+ 'Search emails by criteria.',
180
+ p({
181
+ from: { type: 'string', description: 'Sender address' },
182
+ to: { type: 'string', description: 'Recipient address' },
183
+ subject: { type: 'string', description: 'Subject keyword' },
184
+ text: { type: 'string', description: 'Body text' },
185
+ since: { type: 'string', description: 'Since date (ISO 8601)' },
186
+ before: { type: 'string', description: 'Before date (ISO 8601)' },
187
+ seen: { type: 'boolean', description: 'Filter by read/unread' },
188
+ }),
189
+ 'low',
190
+ async (args) => {
191
+ const provider = getProvider();
192
+ const criteria: SearchCriteria = {};
193
+ if (args.from) criteria.from = String(args.from);
194
+ if (args.to) criteria.to = String(args.to);
195
+ if (args.subject) criteria.subject = String(args.subject);
196
+ if (args.text) criteria.text = String(args.text);
197
+ if (args.since) criteria.since = String(args.since);
198
+ if (args.before) criteria.before = String(args.before);
199
+ if (args.seen !== undefined) criteria.seen = !!args.seen;
200
+ return provider.searchMessages(criteria);
201
+ },
202
+ );
203
+
204
+ defTool('agenticmail_delete', 'Delete Email',
205
+ 'Delete an email by UID.',
206
+ p({
207
+ uid: { type: 'string', description: 'Email UID' },
208
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
209
+ }, ['uid']),
210
+ 'medium',
211
+ async (args) => {
212
+ const provider = getProvider();
213
+ await provider.deleteMessage(String(args.uid), args.folder ? String(args.folder) : undefined);
214
+ return { success: true };
215
+ },
216
+ );
217
+
218
+ defTool('agenticmail_move', 'Move Email',
219
+ 'Move an email to another folder.',
220
+ p({
221
+ uid: { type: 'string', description: 'Email UID' },
222
+ to: { type: 'string', description: 'Destination folder' },
223
+ from: { type: 'string', description: 'Source folder (default INBOX)' },
224
+ }, ['uid', 'to']),
225
+ 'low',
226
+ async (args) => {
227
+ const provider = getProvider();
228
+ await provider.moveMessage(String(args.uid), String(args.to), args.from ? String(args.from) : undefined);
229
+ return { success: true };
230
+ },
231
+ );
232
+
233
+ defTool('agenticmail_mark_read', 'Mark Read',
234
+ 'Mark an email as read.',
235
+ p({ uid: { type: 'string', description: 'Email UID' } }, ['uid']),
236
+ 'low',
237
+ async (args) => {
238
+ const provider = getProvider();
239
+ await provider.markRead(String(args.uid));
240
+ return { success: true };
241
+ },
242
+ );
243
+
244
+ defTool('agenticmail_mark_unread', 'Mark Unread',
245
+ 'Mark an email as unread.',
246
+ p({ uid: { type: 'string', description: 'Email UID' } }, ['uid']),
247
+ 'low',
248
+ async (args) => {
249
+ const provider = getProvider();
250
+ await provider.markUnread(String(args.uid));
251
+ return { success: true };
252
+ },
253
+ );
254
+
255
+ defTool('agenticmail_folders', 'List Folders',
256
+ 'List all mail folders.',
257
+ p({}),
258
+ 'low',
259
+ async () => {
260
+ const provider = getProvider();
261
+ return provider.listFolders();
262
+ },
263
+ );
264
+
265
+ defTool('agenticmail_list_folder', 'List Folder',
266
+ 'List messages in a specific folder.',
267
+ p({
268
+ folder: { type: 'string', description: 'Folder path (e.g. Sent, Trash)' },
269
+ limit: { type: 'number', description: 'Max messages (default 20)' },
270
+ offset: { type: 'number', description: 'Skip messages (default 0)' },
271
+ }, ['folder']),
272
+ 'low',
273
+ async (args) => {
274
+ const provider = getProvider();
275
+ return provider.listMessages(String(args.folder), {
276
+ limit: args.limit ? Number(args.limit) : 20,
277
+ offset: args.offset ? Number(args.offset) : 0,
278
+ });
279
+ },
280
+ );
281
+
282
+ defTool('agenticmail_create_folder', 'Create Folder',
283
+ 'Create a new mail folder.',
284
+ p({ name: { type: 'string', description: 'Folder name' } }, ['name']),
285
+ 'low',
286
+ async (args) => {
287
+ const provider = getProvider();
288
+ await provider.createFolder(String(args.name));
289
+ return { success: true };
290
+ },
291
+ );
292
+
293
+ // ─── Batch Operations ──────────────────────────────────────────────
294
+
295
+ defTool('agenticmail_batch_read', 'Batch Read',
296
+ 'Read multiple emails at once by UIDs.',
297
+ p({
298
+ uids: { type: 'array', description: 'Array of UIDs to read' },
299
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
300
+ }, ['uids']),
301
+ 'low',
302
+ async (args) => {
303
+ const provider = getProvider();
304
+ const uids = (args.uids as string[]).map(String);
305
+ const folder = args.folder ? String(args.folder) : undefined;
306
+ const results = await Promise.all(uids.map(uid => provider.readMessage(uid, folder).catch(err => ({ uid, error: err.message }))));
307
+ return results;
308
+ },
309
+ );
310
+
311
+ defTool('agenticmail_batch_delete', 'Batch Delete',
312
+ 'Delete multiple emails by UIDs.',
313
+ p({
314
+ uids: { type: 'array', description: 'UIDs to delete' },
315
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
316
+ }, ['uids']),
317
+ 'medium',
318
+ async (args) => {
319
+ const provider = getProvider();
320
+ const uids = (args.uids as string[]).map(String);
321
+ const folder = args.folder ? String(args.folder) : undefined;
322
+ await provider.batchDelete(uids, folder);
323
+ return { success: true, count: uids.length };
324
+ },
325
+ );
326
+
327
+ defTool('agenticmail_batch_move', 'Batch Move',
328
+ 'Move multiple emails to another folder.',
329
+ p({
330
+ uids: { type: 'array', description: 'UIDs to move' },
331
+ to: { type: 'string', description: 'Destination folder' },
332
+ from: { type: 'string', description: 'Source folder (default INBOX)' },
333
+ }, ['uids', 'to']),
334
+ 'low',
335
+ async (args) => {
336
+ const provider = getProvider();
337
+ const uids = (args.uids as string[]).map(String);
338
+ await provider.batchMove(uids, String(args.to), args.from ? String(args.from) : undefined);
339
+ return { success: true, count: uids.length };
340
+ },
341
+ );
342
+
343
+ defTool('agenticmail_batch_mark_read', 'Batch Mark Read',
344
+ 'Mark multiple emails as read.',
345
+ p({
346
+ uids: { type: 'array', description: 'UIDs to mark as read' },
347
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
348
+ }, ['uids']),
349
+ 'low',
350
+ async (args) => {
351
+ const provider = getProvider();
352
+ const uids = (args.uids as string[]).map(String);
353
+ await provider.batchMarkRead(uids, args.folder ? String(args.folder) : undefined);
354
+ return { success: true, count: uids.length };
355
+ },
356
+ );
357
+
358
+ defTool('agenticmail_batch_mark_unread', 'Batch Mark Unread',
359
+ 'Mark multiple emails as unread.',
360
+ p({
361
+ uids: { type: 'array', description: 'UIDs to mark as unread' },
362
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
363
+ }, ['uids']),
364
+ 'low',
365
+ async (args) => {
366
+ const provider = getProvider();
367
+ const uids = (args.uids as string[]).map(String);
368
+ await provider.batchMarkUnread(uids, args.folder ? String(args.folder) : undefined);
369
+ return { success: true, count: uids.length };
370
+ },
371
+ );
372
+
373
+ // ─── Agent Identity ────────────────────────────────────────────────
374
+
375
+ defTool('agenticmail_whoami', 'Who Am I',
376
+ 'Get your email identity and account info.',
377
+ p({}),
378
+ 'low',
379
+ async () => {
380
+ const identity = manager.getIdentity?.(agentId);
381
+ if (!identity) return { agentId, note: 'Identity details not available' };
382
+ return { agentId, email: identity.email, name: identity.name };
383
+ },
384
+ );
385
+
386
+ // ─── Inter-Agent Communication ─────────────────────────────────────
387
+
388
+ if (manager.sendAgentMessage) {
389
+ defTool('agenticmail_message_agent', 'Message Agent',
390
+ 'Send a message to another AI agent.',
391
+ p({
392
+ agent: { type: 'string', description: 'Recipient agent ID' },
393
+ subject: { type: 'string', description: 'Message subject' },
394
+ text: { type: 'string', description: 'Message body' },
395
+ priority: { type: 'string', description: 'Priority: normal, high, urgent' },
396
+ }, ['agent', 'subject', 'text']),
397
+ 'medium',
398
+ async (args) => {
399
+ return manager.sendAgentMessage!({
400
+ from: agentId,
401
+ to: String(args.agent),
402
+ subject: String(args.subject),
403
+ body: String(args.text),
404
+ priority: (args.priority as any) || 'normal',
405
+ status: 'pending',
406
+ });
407
+ },
408
+ );
409
+ }
410
+
411
+ if (manager.listAgentMessages) {
412
+ defTool('agenticmail_check_messages', 'Check Messages',
413
+ 'Check for new messages from other agents.',
414
+ p({}),
415
+ 'low',
416
+ async () => {
417
+ return manager.listAgentMessages!(agentId);
418
+ },
419
+ );
420
+ }
421
+
422
+ // ─── Task Management ───────────────────────────────────────────────
423
+
424
+ if (manager.listTasks) {
425
+ defTool('agenticmail_check_tasks', 'Check Tasks',
426
+ 'Check for pending tasks assigned to you.',
427
+ p({
428
+ direction: { type: 'string', description: 'incoming or outgoing (default incoming)' },
429
+ }),
430
+ 'low',
431
+ async (args) => {
432
+ return manager.listTasks!(agentId, (args.direction as any) || 'incoming');
433
+ },
434
+ );
435
+ }
436
+
437
+ if (manager.claimTask) {
438
+ defTool('agenticmail_claim_task', 'Claim Task',
439
+ 'Claim a pending task.',
440
+ p({ id: { type: 'string', description: 'Task ID' } }, ['id']),
441
+ 'low',
442
+ async (args) => manager.claimTask!(String(args.id)),
443
+ );
444
+ }
445
+
446
+ if (manager.completeTask) {
447
+ defTool('agenticmail_complete_task', 'Complete Task',
448
+ 'Claim and submit result in one call.',
449
+ p({
450
+ id: { type: 'string', description: 'Task ID' },
451
+ result: { type: 'object', description: 'Task result data' },
452
+ }, ['id']),
453
+ 'low',
454
+ async (args) => manager.completeTask!(String(args.id), args.result),
455
+ );
456
+ }
457
+
458
+ return tools;
459
+ }
@@ -239,6 +239,7 @@ export class AgentRuntime {
239
239
  var tools = opts.tools || createAllTools({
240
240
  agentId,
241
241
  workspaceDir: process.cwd(),
242
+ agenticmailManager: this.config.agenticmailManager,
242
243
  });
243
244
 
244
245
  var systemPrompt = opts.systemPrompt || buildDefaultSystemPrompt(agentId);
@@ -281,7 +282,7 @@ export class AgentRuntime {
281
282
  var apiKey = this.resolveApiKey(model.provider);
282
283
  if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
283
284
 
284
- var tools = createAllTools({ agentId: session.agentId, workspaceDir: process.cwd() });
285
+ var tools = createAllTools({ agentId: session.agentId, workspaceDir: process.cwd(), agenticmailManager: this.config.agenticmailManager });
285
286
 
286
287
  var agentConfig: AgentConfig = {
287
288
  agentId: session.agentId,
@@ -572,7 +573,7 @@ export class AgentRuntime {
572
573
  continue;
573
574
  }
574
575
 
575
- var tools = createAllTools({ agentId: session.agentId, workspaceDir: process.cwd() });
576
+ var tools = createAllTools({ agentId: session.agentId, workspaceDir: process.cwd(), agenticmailManager: this.config.agenticmailManager });
576
577
 
577
578
  var agentConfig: AgentConfig = {
578
579
  agentId: session.agentId,
@@ -116,6 +116,8 @@ export interface RuntimeConfig {
116
116
  sessionIdleTimeoutMs?: number;
117
117
  /** Enable the runtime gateway (HTTP API) */
118
118
  gatewayEnabled?: boolean;
119
+ /** AgenticMail manager for org email access (optional — enables agenticmail_* tools) */
120
+ agenticmailManager?: import('../agent-tools/tools/agenticmail.js').AgenticMailManagerRef;
119
121
  /** Resume active sessions on startup (default: true) */
120
122
  resumeOnStartup?: boolean;
121
123
  /** Heartbeat interval in ms (default: 30000 = 30s) */