Sends an email to the user via the cloud gateway. The recipient is resolved server-side from the verified session — the agent cannot control who receives the message. Use this to deliver summaries, instructions, or confirmation details that the user will need after the conversation ends.
/** * c_send_email * * Sends an email to the verified user via the cloud gateway. * The gateway resolves the recipient from the session handle — * the agent never controls who receives the message. * * Wire contract * ------------- * POST ${CLOUD_GATEWAY_URL}/api/eoc/email/send * X-Idemeum-Eoc-Api-Key: ${CLOUD_GATEWAY_API_KEY} * X-Idemeum-User-Session: ${userSessionHandle} * Content-Type: application/vnd.dvmi.eoc.email.send+json * Accept: application/vnd.dvmi.eoc.email.send.response+json * Body: { "subject": "...", "body": "..." } * * On success (2xx) the gateway MUST return * { "status": "sent" | "failed", "message": "..." } * — this is the unchanged response contract the client parses; do not * substitute a different success body shape. HTTP status (401/404/502/etc.) * still drives failure classification upstream of this parsing in * cloudGatewayCall — a non-2xx never reaches this body-shape check at all. */import { z } from "zod";import { cloudGatewayCall, type CloudGatewayResult } from "./_shared/cloudGateway";// -- Meta ---------------------------------------------------------------------export const meta = { name: "c_send_email", description: "Sends an email to the user via the cloud gateway. " + "The recipient is resolved server-side from the verified session — " + "the agent cannot control who receives the message. " + "Use this to deliver summaries, instructions, or confirmation details " + "that the user will need after the conversation ends.", riskLevel: "medium", destructive: false, requiresConsent: true, supportsDryRun: false, auditRequired: true, affectedScope: ["network"], requiresVerifiedIdentity: true, sensitiveParams: [], outputKeys: [ "status", "message", "httpStatus", "failureReason", ], schema: { subject: z.string().min(1).max(200).describe( "Email subject line. Keep it short and descriptive.", ), body: z.string().min(1).max(10_000).describe( "Plain-text email body. May include the resolution summary, " + "steps taken, or follow-up instructions for the user.", ), },} as const;// -- Types --------------------------------------------------------------------interface SendEmailData { status: "sent" | "failed"; message: string;}export interface SendEmailResult { status: "ok" | "failed" | "not-configured"; message: string; httpStatus?: number; failureReason?: CloudGatewayResult["failureReason"];}// -- Implementation -----------------------------------------------------------export async function run( args: { subject: string; body: string }, ctx?: { verifiedUpn?: string; userSessionHandle?: string },): Promise<SendEmailResult> { if (!ctx?.verifiedUpn) { return { status: "failed", message: "No verified identity for this run.", } as never; } const r = await cloudGatewayCall<SendEmailData>({ method: "POST", path: "/email/send", body: { subject: args.subject, body: args.body }, userSessionHandle: ctx?.userSessionHandle, contentType: "application/vnd.dvmi.eoc.email.send+json", accept: "application/vnd.dvmi.eoc.email.send.response+json", }); if (r.status !== "ok") { return { status: r.status === "not-configured" ? "not-configured" : "failed", message: r.message, httpStatus: r.httpStatus, failureReason: r.failureReason, }; } const d = r.data!; return { status: d.status === "sent" ? "ok" : "failed", message: d.message, };}