Updates to Agent Copilot summaries in Zendesk

Updates to Agent Copilot summaries in Zendesk

Zendesk’s new ticket summaries make it easier to grasp a conversation at a glance — now available in views, reports, and via API. And with a bit of Action Builder magic, you can even automate summarisation for solved tickets.

One of the more powerful capabilities of LLMs is their ability to convert text into different formats. You can use it to transcribe long conversations and extract key talking points. You can map conversations to intents, assign a sentiment, or extract specific keywords.

Zendesk uses them as part of Agent Copilot's writing tools and intelligent triage to assign meaning to conversations. Agents can easily see why the customer is contacting them and how the customer's feeling at that moment.

One other powerful capability of Agent Copilot is its summarization feature. This lives at the top of a conversation's view and allows agents to summarize a conversation and know what the discussion is about at a glance.

And recently these summaries got a big boost with an expanded length and context window:

[...] ticket summaries have an expanded word limit and can include up to 100 words. Ticket summaries also capture more context, including the core problem, customer expectations, actions taken, outcomes, current status, explicitly stated next steps, key details from the conversation, and more. 

These summaries become useful in a few scenarios. For one, if a ticket gets passed around from team to team, or if you're getting a ticket assigned that another colleague already worked on, you can immediately see what's up without reading the entire conversation.
Similarly, when a customer already talked to your AI Agent before reaching your team, they might already have had a lengthy conversation with that bot. And no one has time to reread that entire thread, especially since you're probably only interested in the escalation reason, and not the steps before that.

Summarization in Agent Workspace offers a solution for both scenarios with its, well, summarizations 😅

Summary of an AI Agent Conversation

Where summaries are useful for Agents, they are equally useful for team leads. Within reporting or QA a summary can give additional context on a ticket that generic intents like "order status inquiry" or "complaint about broken product" miss.

Thanks to a recent update to the platform, these summaries are now no longer limited to just Agent Workspace and have become available in views, analytics and API.

Behind the scenes

My first though when I read summaries would be available via API was a setup like this:

{
  "ticket": {
    "url": "https://d3v-verschoren.zendesk.com/api/v2/tickets/15238.json",
    "id": 15238,
    "subject": "Conversation with Web User 68ed026349e29d2d15bba767",
    "created_at": "1977-05-04T11:38:00Z",
    "summary: "A summary of the ticket conversation",
    ...
  }
}

I assumed summaries would be a new element in the ticket object

In reality, Zendesk hacked the summaries in a more direct way into the API. They created four new system fields to store the generated summary and related metadata.

It's not as elegant, especially since custom fields have a unique id, so instead of extracting e.g. ticket.summary, we need to parse our API data and return ticket.custom_fields[?(@.id==123456789)].value with 123456789 being the ID of our custom field. Which makes that value unique for each Zendesk instance.

Example Postman API call

If we use Postman to retrieve the data of a conversation, we get this data when a ticket is initially created. As you can see, the summary fields return null since there's no summary until an agent generates one.

{
  "ticket": {
    "url": "https://d3v-verschoren.zendesk.com/api/v2/tickets/15238.json",
    "id": 15238,
    "subject": "Conversation with Web User 68ed026349e29d2d15bba767",
    "custom_fields": [
      {
        "id": 29898609074194,
        "value": null
      },
      {
        "id": 29898609076498,
        "value": null
      },
      {
        "id": 29898609078290,
        "value": null
      },
      {
        "id": 29898609079442,
        "value": null
      }
    ]
  }
}

[GET] https://subdomain.zendesk.com/api/v2/tickets/{{ticket.id}}.json

Once an agent generates a summary these fields get filled in, and we can retrieve the summary from the API data.

{
  "ticket": {
    "url": "https://d3v-verschoren.zendesk.com/api/v2/tickets/15238.json",
    "id": 15238,
    "subject": "Conversation with Web User 68ed026349e29d2d15bba767",
    "custom_fields": [
      {
        "id": 29898609074194,
        "value": "The user wanted information on the movie \"Pulp Fiction\" and requested to stream it. The system provided (...)"
      },
      {
        "id": 29898609076498,
        "value": "362397585840"
      },
      {
        "id": 29898609078290,
        "value": "2025-10-13T14:04:15Z"
      },
      {
        "id": 29898609079442,
        "value": "en-US"
      }
    ]
  }
}

[GET} https://subdomain.zendesk.com/api/v2/tickets/{{ticket.id}}.json

Within the returned data we find the summary itself, but also the ID of the agent that last generated the summary, the locale, and creation date of the latest summary.

🤔
I tried PUT or POST to update the API, but it seems these ticket fields are restricted from being updated via the traditional API calls. I did find a workaround, more on that later in the article!

Now that we have summaries available via API calls, you can use them in exports for reporting, integrations, webhook payloads or any other kind of integration you want.

Placeholders and Views

Since summaries are stored in ticket fields, this means we can also access them as placeholders in macros, triggers and automations.

This can be done by adding {{ticket.ticket_field_123456789}} as a placeholder in your text, with 123456789 once again being the ID of the summary field.

One scenario I've been playing around with is adding them as part of the Customer Satisfaction survey emails. This gives customers more information on the thing they're rating, without requiring them to reread the entire thread.

This works, but since automations are written from the company's standpoint, it does look a bit odd for customers. The summary talks about customers in the third person which is not what they would expect.

The user, James Bond, provided his email and inquired for assistance. The agent informed him that Internal Note is a one-person project and response might take a few days, offering alternative contact via email. James thanked the agent, who then advised that the requested content can be streamed on Netflix, Prime, or possibly Apple TV. The user confirmed that the information worked. The conversation ended with the agent wishing James to enjoy his movie. The chat was offline during some exchanges, with prompts to leave an email for notifications. No further actions or issues remain open.

Summaries are also available as columns in views. It's a bit of a weird experience since summaries are longer than other ticket fields and require you to scroll sideways, but they do offer a nice overview at a glance.

Solved tickets and reporting

One scenario where I really love the concept of summaries being available is for reporting and analytics.

Where reporting on intents and categories give high level insights, sometimes you want to dive into a ticket to see what's actually going on. Having those summaries available as part of your Analytics metrics makes it possible to create a dashboard that show specific tickets, and show a summary of that ticket at a glance.

An example of a report that combines intents and summaries

However, there's one big caveat here. Summaries only show up for active tickets where an agent clicked the summarize button. If no summary was generated, it won't show up in your reports. If you generate one after the fact for solved and closed tickets it'll only be accessible in Agent Workspace. Since summaries are stored in custom fields which aren't editable for closed tickets, your summaries won't be accessible over API or views after the fact!

I'd love to see a way to generate summaries for tickets upon solve. This could easily be a trigger or setting in Admin Center and will result in much richer views and reporting. But for now, it's best to actively push Agents to click that summarize button.

There is a workaround however...

Workaround via Custom Actions

I really wanted to automate summarization for solved tickets.

My first idea was to use Custom Actions and leverage the new OpenAI integration to generate a summary via a custom prompt and push that to the Summary ticket field. But since that field is not writable via API, that plan didn't work out.

My second idea fared a bit better. I generated a summary in Agent Workspace while keeping an eye on the Network tab of my browser's developer tools. I noticed an API call being made to subdomain.zendesk.com/api/graphql... which returned a full summary.

I extracted the query and got the following prompt working in Postman. Running this API call resulted in an updated summary in Agent Workspace.

curl --location 'https://subdomain.zendesk.com/api/graphql' \
--header 'Content-Type: application/json' \
--header 'apollographql-client-name: Lotus' \
--header 'apollographql-client-version: v26394' \
--header 'Authorization: ••••••' \
--data '{
  "operationName": "CopilotTicketSummaryGenerate",
  "variables": {
    "input": {
      "ticketId": "15238",
      "locale": "en-US"
    }
  },
  "query": "mutation CopilotTicketSummaryGenerate($input: TicketSummaryGenerateInput!) {\n  ticketSummaryGenerate(input: $input) {\n    ...TicketSummaryGenerateResultData\n    __typename\n  }\n}\n\nfragment TicketSummaryData on TicketSummary {\n  ... on TicketSummaryGenerated {\n    generatedContent\n    __typename\n  }\n  isNewSummaryAvailable\n  timestamp\n  __typename\n}\n\nfragment TicketSummaryGenerateResultData on TicketSummaryGenerateResult {\n  ... on TicketSummaryGenerateError {\n    code\n    message\n    __typename\n  }\n  ... on TicketSummaryGenerated {\n    ...TicketSummaryData\n    __typename\n  }\n  __typename\n}\n"
}'

Replace authorization with a Base64 encoded admin_email/token:api_token

This API call either returned a TicketSummaryGenerated status, or a TicketSummaryGenerateError when the current summary was more recent than the last ticket update.

Now that we can generate summaries on the fly, let's use this to generate them for solved tickets.

🫣
This process reverse engineers a Zendesk API that is not published anywhere. It can break or change at any time and is probably not meant for heavy use. I post it here for educational purposes. If it ever becomes easier to generate them natively, I'll remove this code. Use it wisely!

Custom Actions

For a while now Zendesk has supported custom actions as a way to integrate Agent Copilot with external platforms. But just like you can use webhooks to call Zendesk APIs, we can also use custom actions to integrate with Zendesk.

By creating a new Custom Action that calls the GraphQL API, we can generate summaries automatically right from within the system.

Step one is creating a custom action that asks for a ticket_id as input.

Once you've created the action and added the input, we can start to fill in the API flow as follows:

There are a couple of details to pay attention to:

Authentication requires a custom connection to the Zendesk API. That connection should be of type 'Basic Authentication' It requires an admin email and a valid API token. Use [email protected]/token as the username, and paste in the API token as the password. Use *.zendesk.com as the authorized domain.

The body section can be copied from the code below. Do make sure you replace {{ticket_id}} with an actual placeholder for the Input we created earlier.

{
  "operationName": "CopilotTicketSummaryGenerate",
  "variables": {
    "input": {
      "ticketId": "{{ticket_id}}",
      "locale": "en-US"
    }
  },
  "query": "mutation CopilotTicketSummaryGenerate($input: TicketSummaryGenerateInput!) {\n ticketSummaryGenerate(input: $input) {\n ...TicketSummaryGenerateResultData\n __typename\n }\n}\n\nfragment TicketSummaryData on TicketSummary {\n ... on TicketSummaryGenerated {\n generatedContent\n __typename\n }\n isNewSummaryAvailable\n timestamp\n __typename\n}\n\nfragment TicketSummaryGenerateResultData on TicketSummaryGenerateResult {\n ... on TicketSummaryGenerateError {\n code\n message\n __typename\n }\n ... on TicketSummaryGenerated {\n ...TicketSummaryData\n __typename\n }\n __typename\n}\n"
}

the body of our API call

And finally we need to add three headers:

Header Value
Content-Type application/json
apollographql-client-name Lotus
apollographql-client-version v26394

We don't really need an output, but if you want you can store the __typename into a variable.

You can test your new custom action by entering any ticket id of an active open ticket. You'll either get a successful summary, or an error if there already is a recent summary.

Action Flow

Now that we have a working integration, we need to be able to call the action when a ticket is solved. We can use the new Action Builder for this. We can create an Action flow that runs whenever a ticket is solved, and execute our custom action.

Start by creating a new action flow and name it something like "Summarize on solve". Next add an initial trigger, that reacts to "Ticket | Ticket properties | Ticket status changed". Set the conditions to Variable status , Operation is and Value solved.

Next, add a new step and select our custom action we created previously. Press Save and activate the flow via the context menu top right. Once activated the action flow will run for every solved ticket, and generate a summary.

Conclusion

Having summaries available as part of the native dataset is great. It makes the data contained in tickets available via API, which means it's both exportable and accessible for integrations.

I can already see scenarios where developers would use those summaries in their apps and integrations. You can send the summary of the conversation to Slack when asking another team for help. You could add it to an Asana or Linear task. Add it to reporting, or use it as a basis for pulling insights on tickets.

I'd love a few more updates to this feature in the future. For one, I'd really love to have summaries available as actions in triggers and automations. Making sure a summary is up to date before using it in escalation emails for example.
I'd also like to see them in side conversations. We can already send all or some comments, but maybe a summary would be just as useful.

And finally, I'd love to see two summaries. One that looks at the conversation from a company view, and one that summarizes the interaction for customers. I could see this being useful in the request view on the Help Center, in reminder emails, or as part of the CSAT survey emails.

I’m sure as the platform evolves, and the cost of LLM actions from both a financial and computational standpoint goes down, some of these actions will become available.

Summaries might seem like a small feature, but they solve a very real problem: understanding what happened without reading everything. They turn long conversations into something scannable, searchable, and shareable — across views, reports, and automations.
And now, they’re not just for agents. With API access and integrations, summaries become useful across the wider company — feeding context into workflows, dashboards, or custom tools. Less noise, more clarity, and a faster path to action.