agent

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 26, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ValidateWebhookURL

func ValidateWebhookURL(rawURL string) error

ValidateWebhookImageURL — see ValidateWebhookURL.

ValidateWebhookURL checks that a webhook URL is safe to call (SSRF protection).

Types

type API

type API struct {
	// contains filtered or unexported fields
}

func NewAPI

func NewAPI(store *identity.Store, sender *outbound.Sender, smtpRelay *outbound.SMTPRelay, userAuth *auth.UserAuth, usage usage.UsageTracker, smtpDomain, fromDomain, sharedDomain, publicURL string, production bool) *API

func (*API) RegisterRoutes

func (a *API) RegisterRoutes(r *mux.Router)

func (*API) RegisterWSRoute

func (a *API) RegisterWSRoute(r *mux.Router, handle http.HandlerFunc)

RegisterWSRoute registers the WebSocket endpoint for local-mode agents.

func (*API) SetApprovalSigner

func (a *API) SetApprovalSigner(s *approvaltoken.Signer)

SetApprovalSigner wires in the magic-link signer after construction so callers (and tests) that don't need HITL magic-link endpoints don't have to know about it. When nil, handleApproveMagicLink / handleRejectMagicLink respond with 404.

func (*API) SetNotifier

func (a *API) SetNotifier(n *hitlnotify.Notifier)

SetNotifier wires in the HITL notifier. When nil, holdForApproval still persists the pending message but doesn't fire the email — useful for tests that don't want the async SMTP traffic.

type AgentInfo

type AgentInfo struct {
	ID                   string    `json:"id" example:"ag_abc123"`
	Domain               string    `json:"domain" example:"agents.example.com"`
	Email                string    `json:"email" example:"my-bot@example.com"`
	Name                 string    `json:"name" example:"My Bot"`
	WebhookURL           string    `json:"webhook_url"`
	AgentMode            string    `json:"agent_mode" example:"cloud" enums:"cloud,local"`
	DomainVerified       bool      `json:"domain_verified"`
	CreatedAt            time.Time `json:"created_at"`
	HITLEnabled          bool      `json:"hitl_enabled"`
	HITLTTLSeconds       int       `json:"hitl_ttl_seconds" example:"604800"`
	HITLExpirationAction string    `json:"hitl_expiration_action" example:"reject" enums:"approve,reject"`

} // @name Agent

AgentInfo is the public API representation of an agent.

type ApprovePendingMessageRequest

type ApprovePendingMessageRequest struct {
	Subject     *string      `json:"subject,omitempty"`
	BodyText    *string      `json:"body_text,omitempty"`
	BodyHTML    *string      `json:"body_html,omitempty"`
	To          []string     `json:"to,omitempty"`
	CC          []string     `json:"cc,omitempty"`
	BCC         []string     `json:"bcc,omitempty"`
	Attachments []Attachment `json:"attachments,omitempty"`

} // @name ApprovePendingMessageRequest

ApprovePendingMessageRequest is the optional body for POST /api/v1/messages/{id}/approve. Any field present overrides the stored value before the message is sent; missing fields are left as the original draft. An empty body means approve-as-is.

type ApprovePendingMessageResponse

type ApprovePendingMessageResponse struct {
	Status            string `json:"status" example:"sent"`
	MessageID         string `json:"message_id"`
	ProviderMessageID string `json:"provider_message_id,omitempty"`
	Method            string `json:"method,omitempty" example:"smtp"`
	Edited            bool   `json:"edited,omitempty"`

} // @name ApprovePendingMessageResponse

ApprovePendingMessageResponse is the response when the reviewer approves a held message and the server successfully hands it to the upstream SMTP relay.

type Attachment

type Attachment = outbound.Attachment

Attachment is a base64-encoded file attachment.

type AuthHeaders

type AuthHeaders struct {
	Verified    string `json:"X-E2A-Auth-Verified" example:"true"`
	Sender      string `json:"X-E2A-Auth-Sender" example:"alice@example.com"`
	EntityType  string `json:"X-E2A-Auth-Entity-Type" example:"human" enums:"human,agent"`
	DomainCheck string `json:"X-E2A-Auth-Domain-Check" example:"spf=pass; dkim=none"`
	Delegation  string `json:"X-E2A-Auth-Delegation,omitempty" example:"agent=ag_abc123;human=usr_xyz789"`
	Signature   string `json:"X-E2A-Auth-Signature" example:"sha256=..."`
	Timestamp   string `json:"X-E2A-Auth-Timestamp" example:"2025-01-15T10:30:00Z"`

} // @name AuthHeaders

AuthHeaders documents the signed authentication headers included in webhook deliveries. The server signs Verified, Sender, EntityType, DomainCheck, Delegation, and Timestamp into a canonical string and produces an HMAC-SHA256 Signature. SDKs can verify the signature to confirm the payload was not tampered with.

type DNSRecord

type DNSRecord struct {
	Host     string `json:"host" example:"@"`
	Value    string `json:"value" example:"mx.example.com"`
	Priority *int   `json:"priority,omitempty" example:"10"`

} // @name DNSRecord

DNSRecord is a single DNS record entry.

type DNSRecords

type DNSRecords struct {
	MX  DNSRecord `json:"mx"`
	TXT DNSRecord `json:"txt"`

} // @name DNSRecords

DNSRecords contains the DNS records needed for domain verification.

type DeleteUserDataResult

type DeleteUserDataResult = identity.DeleteUserDataResult // @name DeleteUserDataResult

type DeploymentInfo

type DeploymentInfo struct {
	// SharedDomain is the mail domain backing slug-based agent registration
	// on this deployment (e.g. "agents.example.com"). Empty when the
	// operator hasn't configured one — in that case slug registration is
	// disabled and every agent must use a custom domain.
	SharedDomain string `json:"shared_domain" example:"agents.example.com"`

	// SlugRegistrationEnabled mirrors `shared_domain != ""` for clients
	// that prefer a boolean. Equivalent to checking SharedDomain directly.
	SlugRegistrationEnabled bool `json:"slug_registration_enabled" example:"true"`

	// PublicURL is the externally visible base URL of the API itself —
	// the same value the operator sets in `http.public_url`. Empty when
	// not configured.
	PublicURL string `json:"public_url,omitempty" example:"https://e2a.example.com"`

} // @name DeploymentInfo

DeploymentInfo is the response shape of GET /api/v1/info. It's how CLI/SDK clients discover deployment-specific values (shared domain, public URL) without each user having to configure them by hand.

type DomainInfo

type DomainInfo struct {
	Domain            string     `json:"domain" example:"yourdomain.com"`
	Verified          bool       `json:"verified"`
	VerificationToken string     `json:"verification_token" example:"e2a-verify=abc123"`
	DNSRecords        DNSRecords `json:"dns_records"`
	CreatedAt         time.Time  `json:"created_at"`
	VerifiedAt        *time.Time `json:"verified_at,omitempty"`

} // @name Domain

DomainInfo is the public API representation of a domain.

type ListAgentsResponse

type ListAgentsResponse struct {
	Agents []AgentInfo `json:"agents"`

} // @name ListAgentsResponse

ListAgentsResponse wraps the agent list returned by GET /api/v1/agents.

type ListDomainsResponse

type ListDomainsResponse struct {
	Domains []DomainInfo `json:"domains"`

} // @name ListDomainsResponse

ListDomainsResponse wraps the domain list returned by GET /api/v1/domains.

type ListMessagesResponse

type ListMessagesResponse struct {
	Messages  []MessageSummary `json:"messages"`
	NextToken string           `json:"next_token,omitempty"`

} // @name ListMessagesResponse

ListMessagesResponse wraps the message list with pagination.

type ListPendingMessagesResponse

type ListPendingMessagesResponse struct {
	Messages []PendingMessageSummary `json:"messages"`

} // @name ListPendingMessagesResponse

ListPendingMessagesResponse wraps the array returned by GET /api/v1/messages.

type MessageDetail

type MessageDetail struct {
	MessageID      string            `json:"message_id" example:"msg_abc123"`
	From           string            `json:"from" example:"alice@example.com"`
	To             string            `json:"to" example:"my-bot@example.com"`
	Subject        string            `json:"subject" example:"Hello"`
	ConversationID string            `json:"conversation_id,omitempty"`
	Status         string            `json:"status" example:"read"`
	CreatedAt      string            `json:"created_at"`
	AuthHeaders    map[string]string `json:"auth_headers"`
	RawMessage     string            `json:"raw_message"`

} // @name MessageDetail

MessageDetail is the full message content returned by GET /api/v1/agents/{email}/messages/{id}, which marks unread messages as read when fetched.

type MessageSummary

type MessageSummary struct {
	MessageID      string `json:"message_id" example:"msg_abc123"`
	From           string `json:"from" example:"alice@example.com"`
	To             string `json:"to" example:"my-bot@example.com"`
	Subject        string `json:"subject" example:"Hello"`
	ConversationID string `json:"conversation_id,omitempty"`
	Status         string `json:"status" example:"unread" enums:"unread,read"`
	CreatedAt      string `json:"created_at" example:"2025-01-15T10:30:00Z"`

} // @name MessageSummary

MessageSummary is a lightweight message summary for the list endpoint.

type PendingMessageDetail

type PendingMessageDetail struct {
	PendingMessageSummary
	EmailMessageID    string       `json:"email_message_id,omitempty" example:"<orig@gmail.com>"`
	BodyText          string       `json:"body_text,omitempty"`
	BodyHTML          string       `json:"body_html,omitempty"`
	Attachments       []Attachment `json:"attachments,omitempty"`
	Edited            bool         `json:"edited,omitempty"`
	ReviewedAt        string       `json:"reviewed_at,omitempty" example:"2025-01-15T10:35:00Z"`
	RejectionReason   string       `json:"rejection_reason,omitempty"`
	ProviderMessageID string       `json:"provider_message_id,omitempty"`
	Method            string       `json:"method,omitempty" example:"smtp"`

} // @name PendingMessageDetail

PendingMessageDetail extends the summary with the stored body, attachments, and review metadata. Body columns are populated only while the row is in pending_approval; terminal rows return empty bodies since the server scrubs them on transition.

type PendingMessageSummary

type PendingMessageSummary struct {
	ID                string    `json:"id" example:"msg_abc123"`
	AgentID           string    `json:"agent_id" example:"my-bot@example.com"`
	Direction         string    `json:"direction" example:"outbound"`
	Subject           string    `json:"subject" example:"Re: contract details"`
	Type              string    `json:"type,omitempty" example:"send" enums:"send,reply,test"`
	ConversationID    string    `json:"conversation_id,omitempty"`
	To                []string  `json:"to" example:"alice@example.com"`
	CC                []string  `json:"cc,omitempty"`
	BCC               []string  `json:"bcc,omitempty"`
	Status            string    `json:"status" example:"pending_approval" enums:"sent,pending_approval,rejected,expired_approved,expired_rejected"`
	ApprovalExpiresAt string    `json:"approval_expires_at,omitempty" example:"2025-01-15T10:30:00Z"`
	CreatedAt         time.Time `json:"created_at"`

} // @name PendingMessageSummary

PendingMessageSummary is a row in GET /api/v1/messages?status=pending_approval. Body and attachments are intentionally omitted — fetch the full detail via GET /api/v1/messages/{id} when the reviewer drills in.

type RegisterAgentRequest

type RegisterAgentRequest struct {
	Email      string `json:"email"`
	Slug       string `json:"slug"`
	Name       string `json:"name"`
	WebhookURL string `json:"webhook_url"`
	AgentMode  string `json:"agent_mode"`

} // @name RegisterAgentRequest

type RegisterAgentResponse

type RegisterAgentResponse struct {
	ID     string `json:"id"`
	Domain string `json:"domain"`
	Email  string `json:"email"`

} // @name RegisterAgentResponse

type RegisterDomainRequest

type RegisterDomainRequest struct {
	Domain string `json:"domain" example:"yourdomain.com"`

} // @name RegisterDomainRequest

RegisterDomainRequest is the request body for POST /api/v1/domains.

type RegisterDomainResponse

type RegisterDomainResponse = DomainInfo // @name RegisterDomainResponse

RegisterDomainResponse is the response for POST /api/v1/domains.

type RejectPendingMessageRequest

type RejectPendingMessageRequest struct {
	Reason string `json:"reason,omitempty" example:"wrong recipient"`

} // @name RejectPendingMessageRequest

RejectPendingMessageRequest is the optional body for POST /api/v1/messages/{id}/reject.

type RejectPendingMessageResponse

type RejectPendingMessageResponse struct {
	Status          string `json:"status" example:"rejected"`
	MessageID       string `json:"message_id"`
	RejectionReason string `json:"rejection_reason,omitempty"`

} // @name RejectPendingMessageResponse

RejectPendingMessageResponse is the response when the reviewer rejects a held message.

type ReplyRequest

type ReplyRequest struct {
	Body           string                `json:"body"`
	HTMLBody       string                `json:"html_body,omitempty"`
	ReplyAll       bool                  `json:"reply_all,omitempty"`
	CC             []string              `json:"cc,omitempty"`
	BCC            []string              `json:"bcc,omitempty"`
	ConversationID string                `json:"conversation_id,omitempty"`
	Attachments    []outbound.Attachment `json:"attachments,omitempty"`
}

type ReplyToMessageRequest

type ReplyToMessageRequest struct {
	Body           string       `json:"body" example:"Thanks for your email!"`
	HTMLBody       string       `json:"html_body,omitempty" example:"<p>Thanks for your email!</p>"`
	ReplyAll       bool         `json:"reply_all,omitempty" example:"false"`
	CC             []string     `json:"cc,omitempty" example:"bob@example.com"`
	BCC            []string     `json:"bcc,omitempty" example:"carol@example.com"`
	ConversationID string       `json:"conversation_id,omitempty"`
	Attachments    []Attachment `json:"attachments,omitempty"`

} // @name ReplyToMessageRequest

ReplyToMessageRequest is the request body for replying to a message.

type SendEmailRequest

type SendEmailRequest struct {
	From           string       `json:"from,omitempty" example:"my-bot@example.com"`
	To             []string     `json:"to" example:"alice@example.com"`
	CC             []string     `json:"cc,omitempty" example:"bob@example.com"`
	BCC            []string     `json:"bcc,omitempty" example:"carol@example.com"`
	Subject        string       `json:"subject" example:"Hello from my agent"`
	Body           string       `json:"body" example:"Hi Alice, this is my agent reaching out."`
	HTMLBody       string       `json:"html_body,omitempty" example:"<p>Hi Alice</p>"`
	ConversationID string       `json:"conversation_id,omitempty" example:"conv_abc123"`
	Attachments    []Attachment `json:"attachments,omitempty"`

} // @name SendEmailRequest

SendEmailRequest is the request body for POST /api/v1/send.

type SendEmailResponse

type SendEmailResponse struct {
	Status            string `json:"status" example:"sent" enums:"sent,pending_approval"`
	MessageID         string `json:"message_id" example:"msg_abc123"`
	Method            string `json:"method,omitempty" example:"smtp"`
	ApprovalExpiresAt string `json:"approval_expires_at,omitempty" example:"2025-01-15T10:30:00Z"`

} // @name SendEmailResponse

SendEmailResponse is the response for send and reply operations. When the owning agent has HITL enabled, the server responds with status = "pending_approval" and 202 Accepted; approval_expires_at is set in that case. Otherwise status = "sent" with 200.

type UpdateAgentRequest

type UpdateAgentRequest struct {
	WebhookURL           *string `json:"webhook_url,omitempty"`
	AgentMode            *string `json:"agent_mode,omitempty" enums:"cloud,local"`
	HITLEnabled          *bool   `json:"hitl_enabled,omitempty"`
	HITLTTLSeconds       *int    `json:"hitl_ttl_seconds,omitempty" example:"604800"`
	HITLExpirationAction *string `json:"hitl_expiration_action,omitempty" enums:"approve,reject"`

} // @name UpdateAgentRequest

UpdateAgentRequest is the request body for PUT /api/v1/agents/{email}. All fields are optional; only the fields you send are updated, so callers can PATCH a single setting without re-sending the rest.

type UserExport

type UserExport = identity.UserExport // @name UserExport

type VerifyDomainResponse

type VerifyDomainResponse struct {
	Domain     string     `json:"domain" example:"yourdomain.com"`
	Verified   bool       `json:"verified"`
	VerifiedAt *time.Time `json:"verified_at,omitempty"`

} // @name VerifyDomainResponse

VerifyDomainResponse is the response for POST /api/v1/domains/{domain}/verify.

type WebSocketNotification

type WebSocketNotification struct {
	MessageID      string    `json:"message_id" example:"msg_abc123"`
	ConversationID string    `json:"conversation_id,omitempty"`
	From           string    `json:"from" example:"alice@example.com"`
	To             string    `json:"to" example:"my-bot@example.com"`
	Subject        string    `json:"subject" example:"Hello"`
	ReceivedAt     time.Time `json:"received_at"`

} // @name WebSocketNotification

WebSocketNotification is the lightweight notification sent over WebSocket when a new message arrives for an agent. It contains only metadata — the full message content is fetched via GET /api/v1/agents/{email}/messages/{id}.

type WebhookPayload

type WebhookPayload struct {
	MessageID      string            `json:"message_id" example:"msg_abc123"`
	ConversationID string            `json:"conversation_id,omitempty"`
	From           string            `json:"from" example:"alice@example.com"`
	To             string            `json:"to" example:"agent@yourdomain.com"`
	RawMessage     []byte            `json:"raw_message"`
	AuthHeaders    map[string]string `json:"auth_headers"`
	ReceivedAt     time.Time         `json:"received_at"`

} // @name WebhookPayload

WebhookPayload is the payload delivered to your webhook URL when your agent receives an email. This schema is for documentation only — the actual delivery is handled by the webhook package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL