Support teams using Zendesk face a consistent challenge: a high volume of repetitive tickets that consume agent time, with a smaller fraction of complex issues that genuinely need human expertise. An AI agent integrated with Zendesk can triage incoming tickets, classify and route them intelligently, search the knowledge base for relevant solutions, and draft or post resolutions — all before a human agent ever looks at the ticket.
This guide walks through the full integration from authentication setup to production-ready Python code and no-code configuration.
What AI Agents Can Do With Zendesk Access#
Before configuring anything, it helps to understand the full surface area of Zendesk operations available to an agent:
Reading tickets and data
- Fetch new and open tickets with full conversation history
- Read ticket metadata: requester, organization, channel, tags, priority
- Search tickets by status, assignee, keywords, or custom fields
- Access the requester's full ticket history to understand repeat issues
Writing to tickets
- Add public comments (visible to the customer) or internal notes
- Update ticket properties: priority, status (open, pending, solved), type, tags
- Assign tickets to specific agents or groups based on classification
- Set custom field values (product area, issue category, resolution type)
Knowledge base operations
- Search the Help Center for relevant articles
- Retrieve article full text for RAG-powered resolution generation
- Create new articles when agents identify resolution patterns not yet documented
Workflow automation
- Satisfy trigger conditions that fire Zendesk automations
- Escalate tickets to senior agents programmatically
- Merge duplicate tickets from the same requester
For more background on how agents handle customer interactions, see our AI agent customer service examples.
Authentication Setup#
Zendesk supports two authentication methods for API access: API token (simpler, recommended for agent use) and OAuth (required for multi-tenant applications).
API Token Authentication (Recommended)#
- In Zendesk, go to Admin Center → Apps and Integrations → APIs → Zendesk API
- Under Token Access, click Add API Token
- Give it a descriptive name (e.g., "Triage Agent Production")
- Copy the token immediately — it is shown only once
- Store it in your secrets manager or
.envfile
Your API credentials will be:
- Email: your admin email address
- Token: the token you just generated
- Subdomain: your Zendesk subdomain (the part before
.zendesk.com)
API token authentication uses HTTP Basic Auth with {email}/token:{api_token} as the username.
OAuth Authentication#
OAuth is required when building a multi-tenant integration (e.g., a product that many Zendesk customers will install). For single-workspace agent deployments, API tokens are simpler and sufficient.
To set up OAuth: Admin Center → Apps and Integrations → APIs → OAuth Clients → Add OAuth Client. Configure the redirect URI for your agent's callback endpoint.
Option 1: No-Code Integration with Lindy AI#
Best for: Support teams who want to deploy a triage agent without engineering resources
Step 1: Connect Lindy to Zendesk#
- In your Lindy workspace, go to Integrations → Support → Zendesk
- Authorize with your Zendesk subdomain and admin credentials
- Grant Lindy the requested permissions to read and update tickets
Step 2: Configure the Triage Agent#
Create a new agent with the following system prompt:
You are a Zendesk triage agent for [Company Name] customer support.
When you receive a new ticket:
1. Read the ticket subject and description carefully
2. Classify the issue type from: billing, technical, account, feature_request, general
3. Assess priority: urgent (data loss, security, account locked), high (feature broken, blocking work), normal (general questions), low (feature requests, suggestions)
4. Search the knowledge base for relevant help articles
5. If you find a strong article match (confidence > 85%):
- Add a public comment with the article link and a friendly explanation
- Set the ticket tag 'agent_auto_responded'
- Set the ticket to Pending
6. If no strong match:
- Add an internal note with your classification and routing recommendation
- Assign to the appropriate group based on issue type
- Set the correct priority
Always be professional, empathetic, and concise in customer-facing comments.
Step 3: Set the Trigger#
Configure Lindy to trigger when:
- A new ticket is created in Zendesk
- A ticket status changes to "Open" from "New"
Option 2: LangChain with Python#
Best for: Engineering teams requiring custom resolution logic
Installation#
pip install langchain langchain-openai zenpy python-dotenv
Create a .env file:
ZENDESK_EMAIL=admin@yourcompany.com
ZENDESK_TOKEN=your_api_token
ZENDESK_SUBDOMAIN=yourcompany
OPENAI_API_KEY=sk-...
Build Zendesk Tools#
import os
from zenpy import Zenpy
from zenpy.lib.api_objects import Comment, Ticket
from langchain.tools import tool
from dotenv import load_dotenv
load_dotenv()
creds = {
"email": os.getenv("ZENDESK_EMAIL"),
"token": os.getenv("ZENDESK_TOKEN"),
"subdomain": os.getenv("ZENDESK_SUBDOMAIN")
}
zendesk = Zenpy(**creds)
@tool
def get_ticket(ticket_id: int) -> str:
"""
Fetch a Zendesk ticket by ID. Returns the subject, description,
requester, current status, and existing tags.
"""
ticket = zendesk.tickets(id=ticket_id)
requester = zendesk.users(id=ticket.requester_id)
return (
f"Ticket #{ticket_id}\n"
f"Subject: {ticket.subject}\n"
f"Requester: {requester.name} ({requester.email})\n"
f"Status: {ticket.status}\n"
f"Priority: {ticket.priority}\n"
f"Tags: {', '.join(ticket.tags) if ticket.tags else 'none'}\n"
f"Description: {ticket.description[:800]}"
)
@tool
def add_public_comment(ticket_id: int, comment_text: str) -> str:
"""
Post a public comment to a Zendesk ticket — this is visible to the customer.
Use for resolution suggestions, clarifying questions, or status updates.
"""
ticket = zendesk.tickets(id=ticket_id)
ticket.comment = Comment(body=comment_text, public=True)
zendesk.tickets.update(ticket)
return f"Public comment added to ticket #{ticket_id}"
@tool
def add_internal_note(ticket_id: int, note_text: str) -> str:
"""
Add an internal note to a Zendesk ticket — only visible to agents, not the customer.
Use for routing recommendations, context for the assigned agent, or AI analysis notes.
"""
ticket = zendesk.tickets(id=ticket_id)
ticket.comment = Comment(body=note_text, public=False)
zendesk.tickets.update(ticket)
return f"Internal note added to ticket #{ticket_id}"
@tool
def update_ticket_properties(ticket_id: int, status: str = None,
priority: str = None, tags_to_add: str = None,
assignee_email: str = None) -> str:
"""
Update a Zendesk ticket's properties.
status options: 'open', 'pending', 'hold', 'solved'
priority options: 'urgent', 'high', 'normal', 'low'
tags_to_add: comma-separated list of tags to add
assignee_email: email of the agent to assign the ticket to
"""
ticket = zendesk.tickets(id=ticket_id)
changes = []
if status:
ticket.status = status
changes.append(f"status={status}")
if priority:
ticket.priority = priority
changes.append(f"priority={priority}")
if tags_to_add:
existing_tags = list(ticket.tags or [])
new_tags = [t.strip() for t in tags_to_add.split(",")]
ticket.tags = existing_tags + new_tags
changes.append(f"added tags: {new_tags}")
if assignee_email:
users = list(zendesk.search(f"email:{assignee_email}", type="user"))
if users:
ticket.assignee_id = users[0].id
changes.append(f"assigned to {assignee_email}")
zendesk.tickets.update(ticket)
return f"Ticket #{ticket_id} updated: {', '.join(changes)}"
@tool
def search_knowledge_base(query: str) -> str:
"""
Search Zendesk Help Center articles for content relevant to the query.
Returns the top 3 articles with their titles and URLs.
"""
articles = list(zendesk.help_center.articles.search(query=query))[:3]
if not articles:
return f"No knowledge base articles found for: {query}"
results = []
for article in articles:
results.append(f"- **{article.title}**\n URL: {article.html_url}\n Excerpt: {article.body[:200].strip()}...")
return "Relevant articles:\n" + "\n\n".join(results)
Build the Ticket Triage Agent#
from langchain_openai import ChatOpenAI
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate
llm = ChatOpenAI(model="gpt-4o", temperature=0)
tools = [get_ticket, add_public_comment, add_internal_note,
update_ticket_properties, search_knowledge_base]
triage_prompt = ChatPromptTemplate.from_messages([
("system", """You are an expert Zendesk triage agent for a SaaS company.
When processing a ticket:
1. Read the ticket to understand the issue
2. Search the knowledge base for relevant articles
3. If a highly relevant article is found (directly answers the question):
- Post a public comment with the article link and a helpful explanation
- Update status to 'pending' and add tag 'agent_auto_responded'
4. If no strong match found:
- Add an internal note with: issue type, recommended priority, routing suggestion
- Update the ticket priority to match urgency
- Add the appropriate classification tag
Issue type tags: billing_issue, technical_bug, account_access, feature_request, general_inquiry
Priority logic: 'urgent' if user cannot access account or data loss risk; 'high' if core feature broken;
'normal' for most issues; 'low' for feature requests.
Always be professional and empathetic in public-facing comments."""),
("human", "Process ticket #{ticket_id}"),
("placeholder", "{agent_scratchpad}"),
])
triage_agent = create_tool_calling_agent(llm, tools, triage_prompt)
triage_executor = AgentExecutor(
agent=triage_agent,
tools=tools,
verbose=True,
max_iterations=8
)
# Process a ticket
result = triage_executor.invoke({"ticket_id": "12345"})
print(result["output"])
This is a practical implementation of the AI agent for customer service patterns covered in our tutorials.
Option 3: CrewAI for Multi-Agent Ticket Resolution#
For complex tickets that require multiple reasoning steps — like debugging a technical issue that requires checking both the knowledge base and the customer's account history — a CrewAI crew works well:
from crewai import Agent, Task, Crew
# Agent 1: Researcher reads and analyzes the ticket
ticket_analyst = Agent(
role="Support Ticket Analyst",
goal="Understand the customer's issue and gather all relevant context",
backstory="Expert at reading between the lines of support requests to identify the true underlying issue",
tools=[get_ticket, search_knowledge_base],
llm="gpt-4o"
)
# Agent 2: Resolver drafts the response and updates the ticket
ticket_resolver = Agent(
role="Support Resolution Specialist",
goal="Resolve tickets with accurate, helpful responses and correct routing",
backstory="Experienced support specialist who writes clear, empathetic customer communications",
tools=[add_public_comment, add_internal_note, update_ticket_properties],
llm="gpt-4o"
)
analyze_task = Task(
description="Analyze ticket #{ticket_id}. Read the full ticket, search the knowledge base for relevant solutions, and produce a structured analysis: issue type, severity, relevant articles, and recommended resolution approach.",
agent=ticket_analyst,
expected_output="Structured ticket analysis with issue classification and knowledge base findings"
)
resolve_task = Task(
description="Using the analysis, resolve ticket #{ticket_id}. If a knowledge base article answers the question, post it as a public comment. Otherwise, add an internal note with routing recommendations and update the ticket properties accordingly.",
agent=ticket_resolver,
expected_output="Confirmation of actions taken on the ticket"
)
crew = Crew(
agents=[ticket_analyst, ticket_resolver],
tasks=[analyze_task, resolve_task],
verbose=True
)
result = crew.kickoff(inputs={"ticket_id": "12345"})
For more multi-agent patterns, see the CrewAI multi-agent systems tutorial.
Setting Up Zendesk Triggers to Invoke the Agent#
Configure Zendesk to automatically invoke your agent when new tickets arrive:
- In Zendesk Admin Center, go to Business Rules → Triggers → Add Trigger
- Name: "Invoke AI Triage Agent"
- Conditions:
- Ticket is created
- Channel is not
Voice(avoid triaging phone calls)
- Actions:
- Notify by Webhook → select your webhook target
- JSON body:
{ "ticket_id": "{{ticket.id}}", "subject": "{{ticket.title}}", "requester_email": "{{ticket.requester.email}}" } - Create a Webhook target pointing to your agent endpoint URL
Your agent endpoint receives this payload, extracts the ticket_id, and runs the triage workflow.
Zendesk Sandbox for Safe Testing#
Never test your agent against live production tickets. Zendesk provides a sandbox environment that mirrors your production configuration:
- Enterprise accounts: Full sandbox available under Admin Center → Account → Sandbox
- Professional accounts: Partial sandbox available (configuration only, no ticket data)
- Free testing: Create a separate Zendesk trial account as a test environment
Configure your agent with sandbox credentials during development:
ZENDESK_SUBDOMAIN=yourcompany-sandbox
Test with manually created tickets before pointing the webhook trigger at production.
Security: API Token Permissions#
Follow the principle of least privilege when creating your agent's API token:
| Agent capability | Required Zendesk role | |---|---| | Read all tickets | Agent or above | | Add comments to tickets | Agent or above | | Update ticket status, priority, tags | Agent or above | | Assign tickets to other agents | Agent or above with assignment permissions | | Delete tickets | Admin only — avoid granting this | | Create/modify triggers and automations | Admin only — never grant to agents |
Create a dedicated Zendesk agent account for your AI agent (e.g., ai-agent@yourcompany.com) rather than using an admin's credentials. This limits blast radius if the token is ever compromised and makes audit logs easier to interpret — any ticket update from ai-agent@yourcompany.com was made by the automation.
Monitoring and Quality Control#
Track these metrics to ensure your agent is performing correctly:
- Auto-response rate: Percentage of tickets the agent handles without human intervention
- Reopen rate on auto-closed tickets: High reopen rate indicates the agent is resolving incorrectly
- Customer satisfaction on agent-handled tickets: Compare CSAT scores for agent-handled vs human-handled tickets
- Escalation accuracy: Are the tickets the agent escalates actually the complex ones?
Build a weekly review process where you manually audit a sample of agent-handled tickets to catch systematic errors before they compound.
Next Steps#
Your Zendesk AI agent is ready to handle triage and initial resolution. Expand from here:
- AI Agent Customer Service Tutorial — Comprehensive patterns for customer-facing agents
- AI Agent Customer Service Examples — Real-world implementations with metrics
- AI Agents Explained — Core concepts and terminology
- Best AI Agent Platforms 2026 — Compare LangChain, CrewAI, and Lindy AI for your team
- HubSpot Integration Guide — Connect your agent to CRM data alongside Zendesk
- Browse Integration Templates — Pre-built agent workflow templates for support use cases