import { z } from 'zod';
import type { RegistryApiClient } from '../client/api.js';
export const inboxInputSchema = z.object({
unreadOnly: z.boolean().optional().describe('Only return unread messages'),
threadId: z.string().uuid().optional().describe('Filter by thread ID'),
limit: z.number().int().positive().max(100).optional().describe('Maximum messages to return'),
offset: z.number().int().nonnegative().optional().describe('Offset for pagination'),
markAsRead: z.boolean().optional().describe('Mark returned messages as read'),
});
export type InboxInput = z.infer<typeof inboxInputSchema>;
export interface InboxMessage {
id: string;
threadId: string | null;
from: {
agentId: string;
origin: string;
name?: string;
domain?: string | null;
};
subject?: string | null;
body: string;
metadata?: Record<string, unknown> | null;
signature?: string;
createdAt: string;
readAt: string | null;
}
export interface InboxResult {
success: boolean;
messages?: InboxMessage[];
total?: number;
unread?: number;
error?: string;
}
/**
* Fetch messages from this agent's inbox.
*
* Returns messages sent to this agent by other agents.
* Messages can be filtered by read status or thread.
*/
export async function inbox(
input: InboxInput,
client: RegistryApiClient
): Promise<InboxResult> {
try {
const response = await client.getInbox({
unreadOnly: input.unreadOnly,
threadId: input.threadId,
limit: input.limit,
offset: input.offset,
});
const messages: InboxMessage[] = response.messages.map((m) => ({
id: m.id,
threadId: m.thread_id,
from: {
agentId: m.from_agent_id,
origin: m.from_origin,
name: m.from_agent?.name,
domain: m.from_agent?.domain,
},
subject: m.subject,
body: m.body,
metadata: m.metadata,
signature: m.signature,
createdAt: m.created_at,
readAt: m.read_at,
}));
// Optionally mark messages as read
if (input.markAsRead && messages.length > 0) {
await Promise.all(
messages
.filter((m) => !m.readAt)
.map((m) => client.markAsRead(m.id).catch(() => {
// Silently ignore read-marking failures
}))
);
}
return {
success: true,
messages,
total: response.total,
unread: response.unread,
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Failed to fetch inbox',
};
}
}
export const inboxTool = {
name: 'agents_registry_inbox',
description: 'Fetch messages from this agent\'s inbox. Can filter by read status or conversation thread.',
inputSchema: {
type: 'object' as const,
properties: {
unreadOnly: {
type: 'boolean',
description: 'Only return unread messages',
},
threadId: {
type: 'string',
description: 'Filter messages by conversation thread ID',
},
limit: {
type: 'number',
description: 'Maximum number of messages to return (default: 20, max: 100)',
},
offset: {
type: 'number',
description: 'Offset for pagination',
},
markAsRead: {
type: 'boolean',
description: 'Mark returned messages as read',
},
},
required: [] as string[],
},
};