Skip to content

Add find-similar-open-tickets to catch duplicate Incidents/UserRequests - #4

Open
agent-qv wants to merge 1 commit into
Combodo:masterfrom
agent-qv:pr/find-similar-tickets
Open

agent-qv wants to merge 1 commit into
Combodo:masterfrom
agent-qv:pr/find-similar-tickets

Conversation

@agent-qv

@agent-qv agent-qv commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Closes #3

Problem

The existing ticket search tools are scoped to one caller's email. They cannot detect
that an issue has already been reported by someone else, so an agent has no way to check
for duplicates before creating a new Incident or User Request.

Solution

Adds find-similar-open-tickets, a read-only tool that searches open Incidents and User
Requests by keyword, across all callers, via their common parent class Ticket:

  • Filters on operational_status (ongoing/resolved/closed), the only status attribute
    shared by every ticket class — Ticket itself has no detailed status field.
  • Restricts results to finalclass IN ('Incident','UserRequest') so Problem and
    Change are excluded.
  • Returns candidates without judging whether they match: the server cannot decide that,
    so it hands the agent enough context (title, description, caller, dates) to do so.
  • Sanitizes keywords before they reach the OQL, so they cannot escape their string
    literal or turn into a match-everything (or match-almost-everything) pattern.

An optional ticket_type parameter restricts the search to Incident or UserRequest
alone, and limit caps the number of results.

The existing search tools only look up tickets by caller email, which cannot
answer the question that matters before opening a new ticket: is somebody else
already reporting this? A widespread issue gets reported by many different
callers, so a caller-scoped search comes back empty and a duplicate gets
created.

find-similar-open-tickets searches by keyword across all callers, on both
Incidents and User Requests at once, via their common abstract parent Ticket.
It filters on operational_status, the only status attribute shared by every
ticket class - Ticket itself has no detailed status field, so asking for one
on the parent class would fail. finalclass keeps other Ticket subclasses
(Problem, Change) out of the results.

The tool returns candidates without scoring them: the server has no way to
judge whether two tickets describe the same issue, so it hands the agent
enough context (title, description, caller, dates) to decide. Keywords are
sanitized before reaching the OQL so they cannot escape their string literal
or turn into a match-everything pattern.
Copilot AI balanced review requested due to automatic review settings September 1, 2026 09:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds cross-caller duplicate detection for open Incidents and User Requests.

Changes:

  • Adds keyword-based Ticket search with optional type and result limit.
  • Sanitizes OQL search terms.
  • Adds request and TOON response templates.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/Tools/core/get/iTopGetTools.php Implements the MCP search tool and OQL construction.
templates/findSimilarOpenTickets-input.json.twig Builds the iTop core/get request.
templates/Ticket-output.toon.twig Formats matching tickets for the agent.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +1 to +3
{% if json.objects === null %}
No open ticket matches these keywords in iTop. There is no apparent duplicate.
{% else %}
Comment on lines +161 to +165
default:
// Ticket is the abstract parent of Incident and UserRequest: querying it covers both
// classes at once. finalclass keeps other Ticket subclasses (Problem, Change...) out.
$class = 'Ticket';
$classFilter = " AND finalclass IN ('Incident','UserRequest')";
Comment on lines +185 to +187
$keyword = str_replace(["\\", "'", '"', '%', '_'], '', $keyword);
$keyword = preg_replace('/[\x00-\x1F\x7F]/u', '', $keyword);
return trim($keyword);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Pending review

Development

Successfully merging this pull request may close these issues.

Add a cross-caller search for similar open tickets

3 participants