@agenticmail/enterprise 0.5.51 → 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.
@@ -1,96 +1,63 @@
1
1
  /**
2
- * AgenticMail Agent Tools — Enterprise Adapter
2
+ * AgenticMail Agent Tools — Enterprise Native
3
3
  *
4
- * Wraps the self-contained agenticmail-core tool handlers into
5
- * the enterprise AgentTool format so they integrate with the
6
- * enterprise tool system (middleware, audit, security, etc.).
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.
7
8
  *
8
- * The core tools.ts was written for OpenClaw's registerTool() API.
9
- * This adapter intercepts those registrations and produces AgentTool[].
9
+ * Architecture:
10
+ * Agent tool call
11
+ * → AgenticMailManager.getProvider(agentId)
12
+ * → IEmailProvider (MS Graph / Gmail / IMAP)
13
+ * → Org mailbox
10
14
  */
11
15
 
12
16
  import type { AnyAgentTool, ToolCreationOptions, ToolParameterSchema } from '../types.js';
13
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
+ }
14
33
 
15
- /** AgenticMail API connection config */
16
- export interface AgenticMailConnectionConfig {
17
- /** AgenticMail API base URL (e.g. http://localhost:3141) */
18
- apiUrl: string;
19
- /** Agent API key */
20
- apiKey: string;
21
- /** Master key for admin operations (optional) */
22
- masterKey?: string;
23
- /** Display name for the agent */
24
- ownerName?: string;
34
+ export interface AgenticMailToolsConfig {
35
+ /** The AgenticMailManager instance */
36
+ manager: AgenticMailManagerRef;
37
+ /** The agent ID these tools are for */
38
+ agentId: string;
25
39
  }
26
40
 
27
41
  /**
28
- * Create all AgenticMail tools as enterprise AgentTool objects.
29
- *
30
- * These tools make HTTP calls to the AgenticMail API server.
31
- * They need a running AgenticMail instance to function.
32
- *
33
- * @param connection - AgenticMail API connection config
34
- * @param options - Standard enterprise tool creation options
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.
35
44
  */
36
45
  export function createAgenticMailTools(
37
- connection: AgenticMailConnectionConfig,
46
+ config: AgenticMailToolsConfig,
38
47
  options?: ToolCreationOptions,
39
48
  ): AnyAgentTool[] {
49
+ const { manager, agentId } = config;
40
50
  const tools: AnyAgentTool[] = [];
41
51
 
42
- // ─── HTTP helper (same as agenticmail-core/tools.ts apiRequest) ────
43
-
44
- async function apiRequest(
45
- method: string,
46
- path: string,
47
- body?: unknown,
48
- useMasterKey = false,
49
- timeoutMs = 30_000,
50
- ): Promise<any> {
51
- const key = useMasterKey && connection.masterKey
52
- ? connection.masterKey
53
- : connection.apiKey;
54
- if (!key) {
55
- throw new Error(
56
- useMasterKey
57
- ? 'Master key is required for this operation but was not configured'
58
- : 'API key is not configured',
59
- );
60
- }
61
-
62
- const headers: Record<string, string> = { Authorization: `Bearer ${key}` };
63
- if (body !== undefined) headers['Content-Type'] = 'application/json';
64
-
65
- const response = await fetch(`${connection.apiUrl}/api/agenticmail${path}`, {
66
- method,
67
- headers,
68
- body: body ? JSON.stringify(body) : undefined,
69
- signal: AbortSignal.timeout(timeoutMs),
70
- });
52
+ // ─── Helpers ──────────────────────────────────────────────────────
71
53
 
72
- if (!response.ok) {
73
- let text: string;
74
- try {
75
- text = await response.text();
76
- } catch {
77
- text = '(could not read response body)';
78
- }
79
- throw new Error(`AgenticMail API error ${response.status}: ${text}`);
80
- }
81
-
82
- const contentType = response.headers.get('content-type');
83
- if (contentType?.includes('application/json')) {
84
- try {
85
- return await response.json();
86
- } catch {
87
- throw new Error(`API returned invalid JSON from ${path}`);
88
- }
89
- }
90
- return null;
54
+ function getProvider(): IEmailProvider {
55
+ return manager.getProvider(agentId);
91
56
  }
92
57
 
93
- // ─── Helper: define an agenticmail tool ────────────────────────────
58
+ function p(props: Record<string, any>, required?: string[]): ToolParameterSchema {
59
+ return { type: 'object', properties: props, required };
60
+ }
94
61
 
95
62
  function defTool(
96
63
  name: string,
@@ -110,7 +77,7 @@ export function createAgenticMailTools(
110
77
  execute: async (_toolCallId, args) => {
111
78
  try {
112
79
  const result = await handler(args as Record<string, unknown>);
113
- return jsonResult(result);
80
+ return jsonResult(result ?? { success: true });
114
81
  } catch (err: any) {
115
82
  return errorResult(err.message || String(err));
116
83
  }
@@ -118,46 +85,65 @@ export function createAgenticMailTools(
118
85
  });
119
86
  }
120
87
 
121
- // Helper for simple params
122
- function p(props: Record<string, any>, required?: string[]): ToolParameterSchema {
123
- return { type: 'object', properties: props, required };
124
- }
125
-
126
88
  // ─── Email Core ───────────────────────────────────────────────────
127
89
 
128
90
  defTool('agenticmail_send', 'Send Email',
129
- 'Send an email from the agent mailbox. Outbound guard scans for PII/credentials.',
91
+ 'Send an email from your org mailbox.',
130
92
  p({
131
93
  to: { type: 'string', description: 'Recipient email' },
132
94
  subject: { type: 'string', description: 'Email subject' },
133
95
  text: { type: 'string', description: 'Plain text body' },
134
96
  html: { type: 'string', description: 'HTML body' },
135
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' },
136
102
  }, ['to', 'subject']),
137
103
  'high',
138
- async (args) => apiRequest('POST', '/mail/send', args),
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
+ },
139
119
  );
140
120
 
141
121
  defTool('agenticmail_reply', 'Reply to Email',
142
122
  'Reply to an email by UID.',
143
123
  p({
144
- uid: { type: 'number', description: 'Email UID to reply to' },
124
+ uid: { type: 'string', description: 'Email UID to reply to' },
145
125
  text: { type: 'string', description: 'Reply text' },
146
126
  replyAll: { type: 'boolean', description: 'Reply to all recipients' },
147
127
  }, ['uid', 'text']),
148
128
  'high',
149
- async (args) => apiRequest('POST', `/mail/${args.uid}/reply`, { text: args.text, replyAll: args.replyAll }),
129
+ async (args) => {
130
+ const provider = getProvider();
131
+ return provider.reply(String(args.uid), String(args.text), !!args.replyAll);
132
+ },
150
133
  );
151
134
 
152
135
  defTool('agenticmail_forward', 'Forward Email',
153
136
  'Forward an email to another recipient.',
154
137
  p({
155
- uid: { type: 'number', description: 'Email UID to forward' },
138
+ uid: { type: 'string', description: 'Email UID to forward' },
156
139
  to: { type: 'string', description: 'Recipient to forward to' },
157
140
  text: { type: 'string', description: 'Additional message' },
158
141
  }, ['uid', 'to']),
159
142
  'high',
160
- async (args) => apiRequest('POST', `/mail/${args.uid}/forward`, { to: args.to, text: args.text }),
143
+ async (args) => {
144
+ const provider = getProvider();
145
+ return provider.forward(String(args.uid), String(args.to), args.text ? String(args.text) : undefined);
146
+ },
161
147
  );
162
148
 
163
149
  defTool('agenticmail_inbox', 'List Inbox',
@@ -168,19 +154,25 @@ export function createAgenticMailTools(
168
154
  }),
169
155
  'low',
170
156
  async (args) => {
171
- const qs = new URLSearchParams();
172
- if (args.limit) qs.set('limit', String(args.limit));
173
- if (args.offset) qs.set('offset', String(args.offset));
174
- const q = qs.toString();
175
- return apiRequest('GET', `/mail/inbox${q ? '?' + q : ''}`);
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
+ });
176
162
  },
177
163
  );
178
164
 
179
165
  defTool('agenticmail_read', 'Read Email',
180
166
  'Read a specific email by UID.',
181
- p({ uid: { type: 'number', description: 'Email UID' } }, ['uid']),
167
+ p({
168
+ uid: { type: 'string', description: 'Email UID' },
169
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
170
+ }, ['uid']),
182
171
  'low',
183
- async (args) => apiRequest('GET', `/mail/${args.uid}`),
172
+ async (args) => {
173
+ const provider = getProvider();
174
+ return provider.readMessage(String(args.uid), args.folder ? String(args.folder) : undefined);
175
+ },
184
176
  );
185
177
 
186
178
  defTool('agenticmail_search', 'Search Emails',
@@ -193,60 +185,81 @@ export function createAgenticMailTools(
193
185
  since: { type: 'string', description: 'Since date (ISO 8601)' },
194
186
  before: { type: 'string', description: 'Before date (ISO 8601)' },
195
187
  seen: { type: 'boolean', description: 'Filter by read/unread' },
196
- searchRelay: { type: 'boolean', description: 'Also search connected Gmail/Outlook' },
197
- }),
198
- 'low',
199
- async (args) => apiRequest('POST', '/mail/search', args),
200
- );
201
-
202
- defTool('agenticmail_digest', 'Inbox Digest',
203
- 'Compact inbox digest with subject, sender, date, and preview.',
204
- p({
205
- limit: { type: 'number', description: 'Max messages (default 20)' },
206
- folder: { type: 'string', description: 'Folder (default INBOX)' },
207
- previewLength: { type: 'number', description: 'Preview text length (default 200)' },
208
188
  }),
209
189
  'low',
210
- async (args) => apiRequest('POST', '/mail/digest', args),
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
+ },
211
202
  );
212
203
 
213
204
  defTool('agenticmail_delete', 'Delete Email',
214
205
  'Delete an email by UID.',
215
- p({ uid: { type: 'number', description: 'Email UID' } }, ['uid']),
206
+ p({
207
+ uid: { type: 'string', description: 'Email UID' },
208
+ folder: { type: 'string', description: 'Folder (default INBOX)' },
209
+ }, ['uid']),
216
210
  'medium',
217
- async (args) => apiRequest('DELETE', `/mail/${args.uid}`),
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
+ },
218
216
  );
219
217
 
220
218
  defTool('agenticmail_move', 'Move Email',
221
219
  'Move an email to another folder.',
222
220
  p({
223
- uid: { type: 'number', description: 'Email UID' },
221
+ uid: { type: 'string', description: 'Email UID' },
224
222
  to: { type: 'string', description: 'Destination folder' },
225
223
  from: { type: 'string', description: 'Source folder (default INBOX)' },
226
224
  }, ['uid', 'to']),
227
225
  'low',
228
- async (args) => apiRequest('POST', `/mail/${args.uid}/move`, { to: args.to, from: args.from }),
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
+ },
229
231
  );
230
232
 
231
233
  defTool('agenticmail_mark_read', 'Mark Read',
232
234
  'Mark an email as read.',
233
- p({ uid: { type: 'number', description: 'Email UID' } }, ['uid']),
235
+ p({ uid: { type: 'string', description: 'Email UID' } }, ['uid']),
234
236
  'low',
235
- async (args) => apiRequest('POST', `/mail/${args.uid}/read`),
237
+ async (args) => {
238
+ const provider = getProvider();
239
+ await provider.markRead(String(args.uid));
240
+ return { success: true };
241
+ },
236
242
  );
237
243
 
238
244
  defTool('agenticmail_mark_unread', 'Mark Unread',
239
245
  'Mark an email as unread.',
240
- p({ uid: { type: 'number', description: 'Email UID' } }, ['uid']),
246
+ p({ uid: { type: 'string', description: 'Email UID' } }, ['uid']),
241
247
  'low',
242
- async (args) => apiRequest('POST', `/mail/${args.uid}/unread`),
248
+ async (args) => {
249
+ const provider = getProvider();
250
+ await provider.markUnread(String(args.uid));
251
+ return { success: true };
252
+ },
243
253
  );
244
254
 
245
255
  defTool('agenticmail_folders', 'List Folders',
246
256
  'List all mail folders.',
247
257
  p({}),
248
258
  'low',
249
- async () => apiRequest('GET', '/mail/folders'),
259
+ async () => {
260
+ const provider = getProvider();
261
+ return provider.listFolders();
262
+ },
250
263
  );
251
264
 
252
265
  defTool('agenticmail_list_folder', 'List Folder',
@@ -258,11 +271,11 @@ export function createAgenticMailTools(
258
271
  }, ['folder']),
259
272
  'low',
260
273
  async (args) => {
261
- const qs = new URLSearchParams();
262
- qs.set('folder', String(args.folder));
263
- if (args.limit) qs.set('limit', String(args.limit));
264
- if (args.offset) qs.set('offset', String(args.offset));
265
- return apiRequest('GET', `/mail/list?${qs}`);
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
+ });
266
279
  },
267
280
  );
268
281
 
@@ -270,7 +283,11 @@ export function createAgenticMailTools(
270
283
  'Create a new mail folder.',
271
284
  p({ name: { type: 'string', description: 'Folder name' } }, ['name']),
272
285
  'low',
273
- async (args) => apiRequest('POST', '/mail/folders', { name: args.name }),
286
+ async (args) => {
287
+ const provider = getProvider();
288
+ await provider.createFolder(String(args.name));
289
+ return { success: true };
290
+ },
274
291
  );
275
292
 
276
293
  // ─── Batch Operations ──────────────────────────────────────────────
@@ -282,7 +299,13 @@ export function createAgenticMailTools(
282
299
  folder: { type: 'string', description: 'Folder (default INBOX)' },
283
300
  }, ['uids']),
284
301
  'low',
285
- async (args) => apiRequest('POST', '/mail/batch/read', args),
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
+ },
286
309
  );
287
310
 
288
311
  defTool('agenticmail_batch_delete', 'Batch Delete',
@@ -292,7 +315,13 @@ export function createAgenticMailTools(
292
315
  folder: { type: 'string', description: 'Folder (default INBOX)' },
293
316
  }, ['uids']),
294
317
  'medium',
295
- async (args) => apiRequest('POST', '/mail/batch/delete', args),
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
+ },
296
325
  );
297
326
 
298
327
  defTool('agenticmail_batch_move', 'Batch Move',
@@ -303,7 +332,12 @@ export function createAgenticMailTools(
303
332
  from: { type: 'string', description: 'Source folder (default INBOX)' },
304
333
  }, ['uids', 'to']),
305
334
  'low',
306
- async (args) => apiRequest('POST', '/mail/batch/move', args),
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
+ },
307
341
  );
308
342
 
309
343
  defTool('agenticmail_batch_mark_read', 'Batch Mark Read',
@@ -313,7 +347,12 @@ export function createAgenticMailTools(
313
347
  folder: { type: 'string', description: 'Folder (default INBOX)' },
314
348
  }, ['uids']),
315
349
  'low',
316
- async (args) => apiRequest('POST', '/mail/batch/mark-read', args),
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
+ },
317
356
  );
318
357
 
319
358
  defTool('agenticmail_batch_mark_unread', 'Batch Mark Unread',
@@ -323,463 +362,98 @@ export function createAgenticMailTools(
323
362
  folder: { type: 'string', description: 'Folder (default INBOX)' },
324
363
  }, ['uids']),
325
364
  'low',
326
- async (args) => apiRequest('POST', '/mail/batch/mark-unread', args),
327
- );
328
-
329
- // ─── Agent Communication ──────────────────────────────────────────
330
-
331
- defTool('agenticmail_list_agents', 'List Agents',
332
- 'List all AI agents in the system.',
333
- p({}),
334
- 'low',
335
- async () => apiRequest('GET', '/agents'),
336
- );
337
-
338
- defTool('agenticmail_message_agent', 'Message Agent',
339
- 'Send a message to another AI agent by name.',
340
- p({
341
- agent: { type: 'string', description: 'Recipient agent name' },
342
- subject: { type: 'string', description: 'Message subject' },
343
- text: { type: 'string', description: 'Message body' },
344
- priority: { type: 'string', description: 'Priority: normal, high, urgent' },
345
- }, ['agent', 'subject', 'text']),
346
- 'medium',
347
- async (args) => apiRequest('POST', '/agents/message', args),
348
- );
349
-
350
- defTool('agenticmail_call_agent', 'Call Agent',
351
- 'Call another agent with a task. Supports sync and async modes.',
352
- p({
353
- target: { type: 'string', description: 'Agent name to call' },
354
- task: { type: 'string', description: 'Task description' },
355
- mode: { type: 'string', description: 'light, standard, or full' },
356
- async: { type: 'boolean', description: 'Fire-and-forget (default false)' },
357
- timeout: { type: 'number', description: 'Max seconds to wait (sync only)' },
358
- }, ['target', 'task']),
359
- 'medium',
360
- async (args) => apiRequest('POST', '/agents/call', args, false, 600_000),
361
- );
362
-
363
- defTool('agenticmail_check_messages', 'Check Messages',
364
- 'Check for new unread messages from other agents or external senders.',
365
- p({}),
366
- 'low',
367
- async () => apiRequest('GET', '/agents/messages'),
368
- );
369
-
370
- defTool('agenticmail_check_tasks', 'Check Tasks',
371
- 'Check for pending tasks assigned to you.',
372
- p({
373
- direction: { type: 'string', description: 'incoming or outgoing (default incoming)' },
374
- assignee: { type: 'string', description: 'Check tasks for a specific agent' },
375
- }),
376
- 'low',
377
- async (args) => apiRequest('POST', '/tasks/check', args),
378
- );
379
-
380
- defTool('agenticmail_claim_task', 'Claim Task',
381
- 'Claim a pending task.',
382
- p({ id: { type: 'string', description: 'Task ID' } }, ['id']),
383
- 'low',
384
- async (args) => apiRequest('POST', `/tasks/${args.id}/claim`),
385
- );
386
-
387
- defTool('agenticmail_submit_result', 'Submit Task Result',
388
- 'Submit result for a claimed task.',
389
- p({
390
- id: { type: 'string', description: 'Task ID' },
391
- result: { type: 'object', description: 'Task result data' },
392
- }, ['id']),
393
- 'low',
394
- async (args) => apiRequest('POST', `/tasks/${args.id}/result`, { result: args.result }),
395
- );
396
-
397
- defTool('agenticmail_complete_task', 'Complete Task',
398
- 'Claim and submit result in one call.',
399
- p({
400
- id: { type: 'string', description: 'Task ID' },
401
- result: { type: 'object', description: 'Task result data' },
402
- }, ['id']),
403
- 'low',
404
- async (args) => apiRequest('POST', `/tasks/${args.id}/complete`, { result: args.result }),
405
- );
406
-
407
- defTool('agenticmail_wait_for_email', 'Wait for Email',
408
- 'Wait for a new email or task notification (push-based, SSE).',
409
- p({ timeout: { type: 'number', description: 'Max seconds to wait (default 120)' } }),
410
- 'low',
411
- async (args) => apiRequest('GET', `/mail/wait?timeout=${args.timeout || 120}`, undefined, false, 310_000),
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
+ },
412
371
  );
413
372
 
414
- // ─── Account Management ───────────────────────────────────────────
373
+ // ─── Agent Identity ────────────────────────────────────────────────
415
374
 
416
375
  defTool('agenticmail_whoami', 'Who Am I',
417
- 'Get current agent account info.',
418
- p({}),
419
- 'low',
420
- async () => apiRequest('GET', '/accounts/me'),
421
- );
422
-
423
- defTool('agenticmail_update_metadata', 'Update Metadata',
424
- 'Update current agent metadata.',
425
- p({ metadata: { type: 'object', description: 'Key-value pairs to set' } }, ['metadata']),
426
- 'low',
427
- async (args) => apiRequest('PATCH', '/accounts/me/metadata', { metadata: args.metadata }),
428
- );
429
-
430
- defTool('agenticmail_contacts', 'Manage Contacts',
431
- 'List, add, or delete contacts.',
432
- p({
433
- action: { type: 'string', description: 'list, add, or delete' },
434
- name: { type: 'string', description: 'Contact name (for add)' },
435
- email: { type: 'string', description: 'Contact email (for add)' },
436
- id: { type: 'string', description: 'Contact ID (for delete)' },
437
- }, ['action']),
438
- 'low',
439
- async (args) => apiRequest('POST', '/contacts', args),
440
- );
441
-
442
- // ─── Tags & Labels ────────────────────────────────────────────────
443
-
444
- defTool('agenticmail_tags', 'Manage Tags',
445
- 'List, create, delete tags; tag/untag messages.',
446
- p({
447
- action: { type: 'string', description: 'list, create, delete, tag_message, untag_message, get_messages, get_message_tags' },
448
- name: { type: 'string', description: 'Tag name (for create)' },
449
- color: { type: 'string', description: 'Tag color hex (for create)' },
450
- id: { type: 'string', description: 'Tag ID' },
451
- uid: { type: 'number', description: 'Message UID' },
452
- folder: { type: 'string', description: 'Folder (default INBOX)' },
453
- }, ['action']),
454
- 'low',
455
- async (args) => apiRequest('POST', '/tags', args),
456
- );
457
-
458
- // ─── Drafts ────────────────────────────────────────────────────────
459
-
460
- defTool('agenticmail_drafts', 'Manage Drafts',
461
- 'List, create, update, delete, or send drafts.',
462
- p({
463
- action: { type: 'string', description: 'list, create, update, delete, send' },
464
- id: { type: 'string', description: 'Draft ID (for update/delete/send)' },
465
- to: { type: 'string', description: 'Recipient (for create/update)' },
466
- subject: { type: 'string', description: 'Subject (for create/update)' },
467
- text: { type: 'string', description: 'Body text (for create/update)' },
468
- }, ['action']),
469
- 'medium',
470
- async (args) => apiRequest('POST', '/drafts', args),
471
- );
472
-
473
- // ─── Templates ─────────────────────────────────────────────────────
474
-
475
- defTool('agenticmail_templates', 'Manage Templates',
476
- 'List, create, or delete email templates.',
477
- p({
478
- action: { type: 'string', description: 'list, create, or delete' },
479
- id: { type: 'string', description: 'Template ID (for delete)' },
480
- name: { type: 'string', description: 'Template name (for create)' },
481
- subject: { type: 'string', description: 'Template subject (for create)' },
482
- text: { type: 'string', description: 'Template body (for create)' },
483
- }, ['action']),
484
- 'low',
485
- async (args) => apiRequest('POST', '/templates', args),
486
- );
487
-
488
- defTool('agenticmail_template_send', 'Send Template',
489
- 'Send email using a saved template with variable substitution.',
490
- p({
491
- id: { type: 'string', description: 'Template ID' },
492
- to: { type: 'string', description: 'Recipient email' },
493
- variables: { type: 'object', description: 'Variables to substitute' },
494
- cc: { type: 'string', description: 'CC recipients' },
495
- }, ['id', 'to']),
496
- 'high',
497
- async (args) => apiRequest('POST', '/templates/send', args),
498
- );
499
-
500
- // ─── Signatures ────────────────────────────────────────────────────
501
-
502
- defTool('agenticmail_signatures', 'Manage Signatures',
503
- 'List, create, or delete email signatures.',
504
- p({
505
- action: { type: 'string', description: 'list, create, or delete' },
506
- id: { type: 'string', description: 'Signature ID (for delete)' },
507
- name: { type: 'string', description: 'Signature name (for create)' },
508
- text: { type: 'string', description: 'Signature text (for create)' },
509
- isDefault: { type: 'boolean', description: 'Set as default (for create)' },
510
- }, ['action']),
511
- 'low',
512
- async (args) => apiRequest('POST', '/signatures', args),
513
- );
514
-
515
- // ─── Rules ─────────────────────────────────────────────────────────
516
-
517
- defTool('agenticmail_rules', 'Manage Rules',
518
- 'Server-side email rules that auto-process incoming messages.',
519
- p({
520
- action: { type: 'string', description: 'list, create, or delete' },
521
- id: { type: 'string', description: 'Rule ID (for delete)' },
522
- name: { type: 'string', description: 'Rule name (for create)' },
523
- conditions: { type: 'object', description: 'Match conditions' },
524
- actions: { type: 'object', description: 'Actions on match' },
525
- priority: { type: 'number', description: 'Priority (higher = first)' },
526
- }, ['action']),
527
- 'medium',
528
- async (args) => apiRequest('POST', '/rules', args),
529
- );
530
-
531
- // ─── Scheduled Emails ──────────────────────────────────────────────
532
-
533
- defTool('agenticmail_schedule', 'Scheduled Emails',
534
- 'Create, list, or cancel scheduled emails.',
535
- p({
536
- action: { type: 'string', description: 'create, list, or cancel' },
537
- id: { type: 'string', description: 'Scheduled email ID (for cancel)' },
538
- to: { type: 'string', description: 'Recipient (for create)' },
539
- subject: { type: 'string', description: 'Subject (for create)' },
540
- text: { type: 'string', description: 'Body (for create)' },
541
- sendAt: { type: 'string', description: 'When to send (for create)' },
542
- }, ['action']),
543
- 'medium',
544
- async (args) => apiRequest('POST', '/schedule', args),
545
- );
546
-
547
- // ─── Spam Management ───────────────────────────────────────────────
548
-
549
- defTool('agenticmail_spam', 'Spam Management',
550
- 'List spam, report spam, mark not-spam, or get spam score.',
551
- p({
552
- action: { type: 'string', description: 'list, report, not_spam, or score' },
553
- uid: { type: 'number', description: 'Message UID (for report/not_spam/score)' },
554
- folder: { type: 'string', description: 'Source folder (for report/score)' },
555
- limit: { type: 'number', description: 'Max messages (for list)' },
556
- }, ['action']),
557
- 'low',
558
- async (args) => apiRequest('POST', '/spam', args),
559
- );
560
-
561
- // ─── Pending Emails ────────────────────────────────────────────────
562
-
563
- defTool('agenticmail_pending_emails', 'Pending Emails',
564
- 'Check status of blocked outbound emails.',
565
- p({
566
- action: { type: 'string', description: 'list or get' },
567
- id: { type: 'string', description: 'Pending email ID (for get)' },
568
- }, ['action']),
569
- 'low',
570
- async (args) => apiRequest('POST', '/mail/pending', args),
571
- );
572
-
573
- // ─── Storage (Database) ────────────────────────────────────────────
574
-
575
- defTool('agenticmail_storage', 'Agent Storage',
576
- 'Full database management — tables, CRUD, aggregations, SQL.',
577
- p({
578
- action: { type: 'string', description: 'create_table, query, insert, update, delete_rows, sql, etc.' },
579
- table: { type: 'string', description: 'Table name' },
580
- columns: { type: 'array', description: 'Column definitions (for create_table)' },
581
- rows: { type: 'array', description: 'Row data (for insert/upsert/import)' },
582
- where: { type: 'object', description: 'Filter conditions' },
583
- set: { type: 'object', description: 'Update values' },
584
- sql: { type: 'string', description: 'Raw SQL (for sql action)' },
585
- orderBy: { type: 'string', description: 'ORDER BY clause' },
586
- limit: { type: 'number', description: 'Max rows' },
587
- offset: { type: 'number', description: 'Skip rows' },
588
- selectColumns: { type: 'array', description: 'Columns to select' },
589
- operations: { type: 'array', description: 'Aggregate operations' },
590
- groupBy: { type: 'string', description: 'GROUP BY clause' },
591
- }, ['action']),
592
- 'medium',
593
- async (args) => apiRequest('POST', '/storage', args),
594
- );
595
-
596
- // ─── SMS ───────────────────────────────────────────────────────────
597
-
598
- defTool('agenticmail_sms_setup', 'SMS Setup',
599
- 'Configure SMS/phone via Google Voice.',
600
- p({
601
- phoneNumber: { type: 'string', description: 'Google Voice phone number' },
602
- forwardingEmail: { type: 'string', description: 'Email for SMS forwarding' },
603
- }, ['phoneNumber']),
604
- 'medium',
605
- async (args) => apiRequest('POST', '/sms/setup', args, true),
606
- );
607
-
608
- defTool('agenticmail_sms_send', 'Send SMS',
609
- 'Send an SMS via Google Voice.',
610
- p({
611
- to: { type: 'string', description: 'Recipient phone number' },
612
- body: { type: 'string', description: 'Message text' },
613
- }, ['to', 'body']),
614
- 'high',
615
- async (args) => apiRequest('POST', '/sms/send', args),
616
- );
617
-
618
- defTool('agenticmail_sms_messages', 'SMS Messages',
619
- 'List SMS messages.',
620
- p({
621
- direction: { type: 'string', description: 'inbound, outbound, or both' },
622
- limit: { type: 'number', description: 'Max messages (default 20)' },
623
- }),
624
- 'low',
625
- async (args) => apiRequest('POST', '/sms/messages', args),
626
- );
627
-
628
- defTool('agenticmail_sms_check_code', 'SMS Check Code',
629
- 'Check for recent verification/OTP codes.',
630
- p({ minutes: { type: 'number', description: 'How many minutes back (default 10)' } }),
631
- 'low',
632
- async (args) => apiRequest('POST', '/sms/check-code', args),
633
- );
634
-
635
- defTool('agenticmail_sms_config', 'SMS Config',
636
- 'Get current SMS/phone configuration.',
376
+ 'Get your email identity and account info.',
637
377
  p({}),
638
378
  'low',
639
- async () => apiRequest('GET', '/sms/config'),
640
- );
641
-
642
- defTool('agenticmail_sms_record', 'Record SMS',
643
- 'Record an SMS message from an external source.',
644
- p({
645
- from: { type: 'string', description: 'Sender phone number' },
646
- body: { type: 'string', description: 'Message text' },
647
- }, ['from', 'body']),
648
- 'low',
649
- async (args) => apiRequest('POST', '/sms/record', args),
650
- );
651
-
652
- defTool('agenticmail_sms_parse_email', 'Parse SMS Email',
653
- 'Parse SMS from a forwarded Google Voice email.',
654
- p({
655
- emailBody: { type: 'string', description: 'Email body text' },
656
- emailFrom: { type: 'string', description: 'Email sender address' },
657
- }, ['emailBody']),
658
- 'low',
659
- async (args) => apiRequest('POST', '/sms/parse-email', args),
660
- );
661
-
662
- // ─── Admin Operations (require master key) ────────────────────────
663
-
664
- defTool('agenticmail_create_account', 'Create Agent Account',
665
- 'Create a new agent email account.',
666
- p({
667
- name: { type: 'string', description: 'Agent name' },
668
- domain: { type: 'string', description: 'Email domain' },
669
- role: { type: 'string', description: 'Agent role' },
670
- }, ['name']),
671
- 'high',
672
- async (args) => apiRequest('POST', '/accounts', args, true),
673
- );
674
-
675
- defTool('agenticmail_delete_agent', 'Delete Agent',
676
- 'Delete an agent account permanently.',
677
- p({
678
- name: { type: 'string', description: 'Agent name to delete' },
679
- reason: { type: 'string', description: 'Reason for deletion' },
680
- }, ['name']),
681
- 'critical',
682
- async (args) => apiRequest('DELETE', `/accounts/${encodeURIComponent(String(args.name))}`, { reason: args.reason }, true),
683
- );
684
-
685
- defTool('agenticmail_cleanup', 'Cleanup Agents',
686
- 'List or remove inactive agent accounts.',
687
- p({
688
- action: { type: 'string', description: 'list_inactive, cleanup, or set_persistent' },
689
- hours: { type: 'number', description: 'Inactivity threshold (default 24)' },
690
- dryRun: { type: 'boolean', description: 'Preview only' },
691
- agentId: { type: 'string', description: 'Agent ID (for set_persistent)' },
692
- persistent: { type: 'boolean', description: 'Set persistent flag' },
693
- }, ['action']),
694
- 'high',
695
- async (args) => apiRequest('POST', '/accounts/cleanup', args, true),
696
- );
697
-
698
- defTool('agenticmail_status', 'Server Status',
699
- 'Check AgenticMail server health.',
700
- p({}),
701
- 'low',
702
- async () => apiRequest('GET', '/status'),
703
- );
704
-
705
- // ─── Gateway & Setup ──────────────────────────────────────────────
706
-
707
- defTool('agenticmail_gateway_status', 'Gateway Status',
708
- 'Check email gateway status (relay, domain, or none).',
709
- p({}),
710
- 'low',
711
- async () => apiRequest('GET', '/gateway/status', undefined, true),
712
- );
713
-
714
- defTool('agenticmail_setup_relay', 'Setup Relay',
715
- 'Configure Gmail/Outlook relay for internet email.',
716
- p({
717
- provider: { type: 'string', description: 'gmail, outlook, or custom' },
718
- email: { type: 'string', description: 'Your real email' },
719
- password: { type: 'string', description: 'App password' },
720
- }, ['provider', 'email', 'password']),
721
- 'critical',
722
- async (args) => apiRequest('POST', '/gateway/setup-relay', args, true),
723
- );
724
-
725
- defTool('agenticmail_setup_domain', 'Setup Domain',
726
- 'Set up custom domain via Cloudflare for internet email.',
727
- p({
728
- cloudflareToken: { type: 'string', description: 'Cloudflare API token' },
729
- cloudflareAccountId: { type: 'string', description: 'Cloudflare account ID' },
730
- domain: { type: 'string', description: 'Domain to use' },
731
- }, ['cloudflareToken', 'cloudflareAccountId']),
732
- 'critical',
733
- async (args) => apiRequest('POST', '/gateway/setup-domain', args, true),
734
- );
735
-
736
- defTool('agenticmail_import_relay', 'Import Relay Email',
737
- 'Import an email from connected Gmail/Outlook into local inbox.',
738
- p({ uid: { type: 'number', description: 'Relay UID to import' } }, ['uid']),
739
- 'low',
740
- async (args) => apiRequest('POST', '/mail/import-relay', { uid: args.uid }),
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
+ },
741
384
  );
742
385
 
743
- defTool('agenticmail_test_email', 'Test Email',
744
- 'Send a test email to verify configuration.',
745
- p({ to: { type: 'string', description: 'Test recipient' } }, ['to']),
746
- 'medium',
747
- async (args) => apiRequest('POST', '/gateway/test', { to: args.to }, true),
748
- );
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
+ }
749
410
 
750
- defTool('agenticmail_deletion_reports', 'Deletion Reports',
751
- 'List or get agent deletion reports.',
752
- p({ id: { type: 'string', description: 'Report ID (omit to list all)' } }),
753
- 'low',
754
- async (args) => apiRequest('GET', args.id ? `/accounts/deletion-reports/${args.id}` : '/accounts/deletion-reports', undefined, true),
755
- );
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
+ }
756
421
 
757
- defTool('agenticmail_setup_guide', 'Setup Guide',
758
- 'Get comparison of email setup modes.',
759
- p({}),
760
- 'low',
761
- async () => apiRequest('GET', '/gateway/setup-guide', undefined, true),
762
- );
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
+ }
763
436
 
764
- defTool('agenticmail_setup_gmail_alias', 'Gmail Alias Setup',
765
- 'Get instructions for adding agent email as Gmail Send-As alias.',
766
- p({
767
- agentEmail: { type: 'string', description: 'Agent email to add as alias' },
768
- agentDisplayName: { type: 'string', description: 'Display name for alias' },
769
- }, ['agentEmail']),
770
- 'low',
771
- async (args) => apiRequest('POST', '/gateway/gmail-alias', args, true),
772
- );
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
+ }
773
445
 
774
- defTool('agenticmail_purchase_domain', 'Search Domains',
775
- 'Search for available domains via Cloudflare.',
776
- p({
777
- keywords: { type: 'array', description: 'Search keywords' },
778
- tld: { type: 'string', description: 'Preferred TLD' },
779
- }, ['keywords']),
780
- 'low',
781
- async (args) => apiRequest('POST', '/gateway/search-domains', args, true),
782
- );
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
+ }
783
457
 
784
458
  return tools;
785
459
  }