MCPcopy Create free account
hub / github.com/Mnexa-AI/e2a / HoldForApprovalCore

Method HoldForApprovalCore

internal/agent/api.go:1029–1067  ·  view source on GitHub ↗

HoldForApprovalCore is the HTTP-free core of the HITL hold: it persists the pending outbound message, fires the async reviewer notification, and publishes the pending-approval event, returning the held message. Both the legacy handler and the v1 httpapi layer call it so there is exactly one hold-and

(ctx context.Context, agent *identity.AgentIdentity, req outbound.SendRequest, msgType, replyToEmailMessageID string)

Source from the content-addressed store, hash-verified

1027// legacy handler and the v1 httpapi layer call it so there is exactly one
1028// hold-and-notify path (api-v1-redesign — outbound extraction).
1029func (a *API) HoldForApprovalCore(ctx context.Context, agent *identity.AgentIdentity, req outbound.SendRequest, msgType, replyToEmailMessageID string) (*identity.Message, error) {
1030 var attachmentsJSON []byte
1031 if len(req.Attachments) > 0 {
1032 b, err := json.Marshal(req.Attachments)
1033 if err != nil {
1034 log.Printf("[api] hitl: marshal attachments: %v", err)
1035 return nil, errHoldAttachments
1036 }
1037 attachmentsJSON = b
1038 }
1039
1040 msg, err := a.store.CreatePendingOutboundMessage(
1041 ctx, agent.ID,
1042 req.To, req.CC, req.BCC,
1043 req.Subject, req.Body, req.HTMLBody,
1044 attachmentsJSON,
1045 msgType, req.ConversationID, replyToEmailMessageID,
1046 agent.HITLTTLSeconds,
1047 )
1048 if err != nil {
1049 log.Printf("[api] hitl: create pending message: agent=%s err=%v", agent.ID, err)
1050 return nil, err
1051 }
1052
1053 slug, _, _ := strings.Cut(agent.EmailAddress(), "@")
1054 log.Printf("[mail:%s] dir=outbound type=%s status=%s from=%s to=%v slug=%s conv_id=%s subject=%q approval_expires_at=%s",
1055 msg.ID, msgType, msg.Status, agent.EmailAddress(), req.To, slug, req.ConversationID, req.Subject, msg.ApprovalExpiresAt.Format(time.RFC3339))
1056
1057 // Fire the reviewer notification asynchronously. Failures are logged
1058 // inside the notifier and must never block the response — the pending
1059 // row is already persisted and the expiration worker will finalize it
1060 // even if every notification email bounces.
1061 if a.notifier != nil {
1062 a.notifier.NotifyPendingApprovalAsync(msg, agent)
1063 }
1064
1065 a.publishPendingApproval(ctx, a.buildPendingApprovalEvent(agent, msg, req, msgType), msg.ID)
1066 return msg, nil
1067}
1068
1069// OutboundResult is the HTTP-free outcome of DeliverOutbound.
1070type OutboundResult struct {

Callers 2

DeliverOutboundMethod · 0.95
SendTestCoreMethod · 0.95

Calls 5

EmailAddressMethod · 0.80

Tested by

no test coverage detected