package contract import ( "context" "errors" ) type BusinessActionFailureOutcome string const ( // BusinessActionFailureRetryable means execution failed before the host // operation could have produced a side effect. The same idempotency key may // be claimed again. BusinessActionFailureRetryable BusinessActionFailureOutcome = "retryable_failed" // BusinessActionFailureUnknown means the host may have committed the side // effect even though Agent Desk did not receive a definitive response. Such // an invocation must be reconciled instead of replayed automatically. BusinessActionFailureUnknown BusinessActionFailureOutcome = "unknown_outcome" ) // BusinessActionResult is the customer-safe result returned after a confirmed // host business operation. Message is sent to the customer verbatim; Data is // retained only for idempotent replay and future structured clients. type BusinessActionResult struct { Message string `json:"message"` Data any `json:"data,omitempty"` } // BusinessActionError separates a customer-safe explanation from its internal // cause so model observations and chat replies never expose infrastructure // errors returned by the host application. type BusinessActionError struct { Message string Cause error Outcome BusinessActionFailureOutcome } func (e *BusinessActionError) Error() string { return e.Message } func (e *BusinessActionError) Unwrap() error { return e.Cause } func NewBusinessActionError(message string, cause error) error { return &BusinessActionError{Message: message, Cause: cause, Outcome: BusinessActionFailureUnknown} } func NewRetryableBusinessActionError(message string, cause error) error { return &BusinessActionError{Message: message, Cause: cause, Outcome: BusinessActionFailureRetryable} } func NewUnknownOutcomeBusinessActionError(message string, cause error) error { return &BusinessActionError{Message: message, Cause: cause, Outcome: BusinessActionFailureUnknown} } func BusinessActionErrorOutcome(err error) BusinessActionFailureOutcome { var actionErr *BusinessActionError if errors.As(err, &actionErr) { return actionErr.Outcome } return "" } // BusinessActionTool lets the host expose a narrowly scoped write operation. // Preview must perform read-only validation and produce the exact confirmation // prompt. Execute must independently reload and validate all mutable business // state before committing the operation. type BusinessActionTool struct { Code string Description string CustomerTypes []string InputSchema map[string]any // MatchIntent lets the host identify an unambiguous customer command that // must enter the confirmation flow without relying on the language model to // select a tool. It must be side-effect free. MatchIntent func(string) bool Preview func(context.Context, BusinessReadContext, map[string]any) (string, error) // BindConfirmation binds the generated server checkpoint and canonical // arguments to the verified request that prepared the action. BindConfirmation func(context.Context, BusinessReadContext, map[string]any, string) error // AuthorizeConfirmation re-verifies the current confirmation request and // the previously bound checkpoint immediately before idempotency claiming. AuthorizeConfirmation func(context.Context, BusinessReadContext, map[string]any, string) error Execute func(context.Context, BusinessReadContext, map[string]any) (*BusinessActionResult, error) }