> ## Documentation Index
> Fetch the complete documentation index at: https://docs.checkfu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Support desk

> Wrap an existing support stack with a Checkfu Session, governed tools, approvals, and honest provider-effect handling.

A support desk can add an Agent without moving ticket ownership or business logic into Checkfu. The support application remains the source of ticket state. Your service sends each ticket conversation to one Checkfu Session through the ordinary Session API, and custom tools call the same application functions used by the human-facing UI.

Start with the [quickstart](/getting-started/quickstart). In one Workspace, create or update an [Agent](/concepts/agents), select an [Environment](/concepts/work-environments), and start a [Session](/concepts/sessions-and-runs). Session admission freezes the resolved AgentVersion and Environment authority. Every later interaction is read from and appended to the Session event log.

## What this example demonstrates

1. Verify each incoming support message in your service, then send it to the one Session you keep for that ticket conversation. Your service owns the ticket-to-Session map.
2. Project the Session event log into the support UI instead of maintaining a second transcript.
3. Expose ticket functions as Custom tools declared on the Agent. ActionPolicy chooses `allow`, `require_approval`, or `deny` for each call, and a required ActionApproval records the exact human decision on the frozen call.
4. Run the handler in the support application. Approval is not execution: an approved call still waits until the application checks its own tenant, account, and ticket access, runs the handler, and returns the correlated result. A call for a ticket the caller cannot reach is refused there, by the application.
5. Keep connected tools on their own path. A tool that acts through a Connection (for example, sending email through a provider account) is checked against governed account access, policy, and any required approval, and executes inside Checkfu's trusted provider boundary rather than in the support application.
6. Deliver accepted Session output downstream from your service. Provider acknowledgement is not Checkfu custody, and provider redelivery is not a new Agent turn unless the message key is new.

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
Support provider
  │ verified message
  ▼
Your service
  │ POST /v1/sessions/{id}/events, read events, deliver replies
  ▼
Session → Run → durable event log
  │
  ├── Custom tool call → ActionPolicy → ActionApproval (if required)
  │     → support application: ticket access check → handler → result
  └── connected tool call → account access → ActionPolicy → ActionApproval (if required)
        → provider execution inside Checkfu
```

Sending a reply, closing a ticket, or changing an external record is a provider or application effect. If the request may have succeeded but the response was lost, record an indeterminate result and reconcile against the source of truth before retrying. Exactly-once delivery is not assumed.

## Retention, erasure, and support boundaries

Standard retention may preserve permitted support messages, tool content, and Session events under policy. Under ZDR, admitted execution can stream only through eligible live custody and is not durably retained, so later transcript replay and content recovery are unavailable. A production erasure claim is valid only when every governed sink and in-flight export is fenced before completion. Permitted non-content Audit and Usage facts may remain identifiable or pseudonymous; see [retention and ZDR](/concepts/retention-and-zdr) for their separate retention boundaries. Usage, not UI analytics or traces, drives Budgets.

A provider adapter, deterministic fixture, or successful local demo does not establish production support. The exact provider and deployment must qualify restart recovery, revocation, and erasure. Consult [capability status](/getting-started/status) for those gates and for the custom-tool, approval, Connection, and execution prerequisites.

## Pinned source boundary

The optional source builds tool declarations from the same application functions as the human routes. Its `needsActionApproval` field is the SDK declaration that `tools.sync` reconciles into a governed ActionPolicy requiring approval; the field is not itself approval authority. The handler's `ticket_scope_mismatch` result is the application-side access check: it runs after any approval, so an approved call for the wrong ticket still does nothing.

```ts path=examples/support-desk/server/src/agent-tools.ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
	defineTool({
		name: "close_ticket",
		description: "Close a resolved support ticket after a human approves the frozen call.",
		schema: ticketIdSchema,
		needsActionApproval: true,
		handler: (input: JsonValue, context: TicketExecutionContext) => {
			const { ticket_id } = readTicketArguments(input)
			return ticket_id === ticketId
				? actions.closeTicket({ ticket_id: ticketId }, context)
				: {
						ok: false,
						error: "ticket_scope_mismatch",
						ticket_id,
						expected_ticket_id: ticketId,
					}
		},
	}),
```

## What this example omits

This page does not move ticket state into the Session, create provider-side approval authority, claim exactly-once delivery to the provider, treat a webhook body as a second transcript, or present a fixture provider as production-supported.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.