FixFlow
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@FixFlowMy laptop won't charge; serial PF7Q2M88. What should I do?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
FixFlow: AI agent for IT-support triage
FixFlow reads a support request written in plain language, such as "my laptop is plugged in but stuck at 80%", and decides what should happen next:
Self-serve: answer with steps from the right troubleshooting article, with a citation.
Ticket: open a ticket and route it to the right team (hardware repair, network ops, software support or IT helpdesk).
Escalate: hand it to a person when it is a safety or security risk, the user asks for a human, data is at risk, or the agent is not confident.
It also checks the device's warranty and explains every decision in a step-by-step trace.
Live demo: fixflow-nehm.onrender.com: type a problem and watch the agent's pipeline run step by step, then click any report on the live issue board to see why the AI decided what it did. (Free hosting: the first visit can take up to 50 seconds to wake up.)
Measured on a held-out test set of 30 labeled tickets: 100% correct action, 90% correct category, and every safety case escalated (2 of 2). Full results.
$ python -m fixflow "The bottom of my laptop is bulging" --serial PF7Q2M88 --trace
Action: escalate
Category: safety_hazard -> team: safety_response
Urgency: critical confidence: 1.00
Why: Possible safety hazard: always handled by a person.
Ticket: FF-60B9B46C
I've passed this to a support specialist (ticket FF-60B9B46C). Someone will contact you directly.
1. Stop using the device. Unplug the charger if it is safe to do so.
2. Do not charge it, press on it, or try to remove the battery yourself.
...
Note: your AeroBook 14 Gen 3 warranty ended on 2026-01-20, so repairs are paid.
Trace:
- retrieve: KB-005 (5.25), KB-003 (4.35), KB-007 (1.28)
- triage[offline]: category=safety_hazard urgency=critical confidence=1.00
- check_warranty: {'serial': 'PF7Q2M88', 'model': 'AeroBook 14 Gen 3', 'plan': 'base', ...}
- decide: escalate -> safety_response (Possible safety hazard: always handled by a person.)
- act: ticket FF-60B9B46CWhat's inside
Piece | What it does | Where |
Retrieval from scratch | Tokenizer, BM25 ranking and an inverted index, written by hand with no vector database |
|
Guarded LLM triage | Claude or OpenAI returns schema-validated JSON; safety rules can only make the result more careful |
|
Agent workflow | retrieve → triage → check warranty → decide → act → explain, with a full trace |
|
Tools | Warranty lookup, ticket creation, human escalation (SQLite), approved-software catalog |
|
MCP server | Exposes the tools to any MCP client, such as Claude Desktop |
|
REST API | FastAPI service: |
|
Demo web app | Animated single-file front end: live agent pipeline, streaming trace, issue board fed from the database |
|
Evaluation | 50 labeled tickets split into dev and held-out test sets; CI fails if quality drops |
|
Production basics | 41 tests, fake LLM clients, Docker image with health check, GitHub Actions CI |
|
Related MCP server: soporte-ti-mcp
Architecture
flowchart LR
U[User request] --> R[Retrieve<br/>BM25 over KB]
R --> T[Triage<br/>LLM or offline]
G[Safety and security rules] -. can only add caution .-> T
T --> W[check_warranty]
W --> D{Decide}
D -->|safety, security, wants human,<br/>data at risk, low confidence| E[Escalate to person]
D -->|damage, already tried,<br/>outage, unapproved app| K[Open ticket<br/>routed to team]
D -->|KB covers it| S[Self-serve answer<br/>with citation]
E & K & S --> O[Resolution + trace]
subgraph Interfaces
CLI[CLI] --- API[REST API] --- MCP[MCP server]
end
O --> InterfacesQuick start
git clone https://github.com/YOUR_GITHUB_USERNAME/fixflow.git
cd fixflow
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements-dev.txt
python -m fixflow "wifi keeps disconnecting every 10 minutes" --trace # CLI
pytest -q # tests
python -m fixflow.evals --compare # evaluation
uvicorn fixflow.api:app --reload # API at http://localhost:8000/docsEverything above runs offline with no API key. To use a real LLM, copy .env.example to .env, or export:
export FIXFLOW_PROVIDER=anthropic # or openai
export ANTHROPIC_API_KEY=sk-... # or OPENAI_API_KEY
python -m fixflow "my screen flickers when I scroll"Free option (Groq): Groq offers a free plan with an OpenAI-compatible API. Create a key at console.groq.com, then:
export FIXFLOW_PROVIDER=openai
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
export OPENAI_API_KEY=gsk_... # your Groq key
export FIXFLOW_MODEL=openai/gpt-oss-120bIf the free limit is hit or the API fails, FixFlow falls back to the offline triager automatically, and the trace says so.
With Docker:
docker build -t fixflow . && docker run --rm -p 8000:8000 fixflow
curl -X POST localhost:8000/triage -H 'content-type: application/json' \
-d '{"text": "I spilled coffee on my keyboard", "serial": "PF3K9X21"}'Use it from Claude Desktop (MCP)
FixFlow runs as an MCP server with five tools: triage_request, search_manuals, check_warranty, create_ticket and get_ticket.
Install the project as shown in Quick start.
Open Claude Desktop → Settings → Developer → Edit Config, and add the block from
examples/claude_desktop_config.jsonwith your real paths.Restart Claude Desktop and ask: "Check the warranty for NV5T1R43 and open a ticket for its cracked screen."
Evaluation
The project includes 50 hand-labeled tickets (data/eval/tickets.jsonl) covering typos, vague requests, repeat reports, outages and safety cases. They are split into:
dev (20 tickets): the only tickets used while building and tuning.
test (30 tickets): held out and run once, after tuning was finished.
Results with the offline triager, comparing the baseline retriever (v1) with the improved one (v2: light stemming, a title field boost, and one synonym rule added after a dev failure):
Metric | test, v1 | test, v2 |
Correct action (self-serve / ticket / escalate) | 96.7% | 100% |
Correct category | 86.7% | 90.0% |
Correct team | 86.7% | 93.3% |
Retrieval hit@1 / hit@3 | 73.3% / 86.7% | 76.7% / 86.7% |
Escalation precision / recall | 85.7% / 100% | 100% / 100% |
Safety cases escalated | 2/2 | 2/2 |
Time per ticket | 0.2 ms | 0.3 ms |
Full output, including every miss, is in results/eval_offline.md. Run FIXFLOW_PROVIDER=anthropic python -m fixflow.evals --compare to produce the same table for the LLM triager.
Known misses on the test set:
"VPN says authentication failed" is filed as an account problem rather than a network one.
"Office keeps saying unlicensed product" is not recognised as a software issue.
"pc not working" gets an arbitrary category. Its action is still correct: it goes to a person, because confidence is low.
Honest limits: the knowledge base, devices and tickets are synthetic and were written for this project by the same person who built the system. 30 test tickets is small, so treat these numbers as a sanity check, not a benchmark.
Design decisions
Workflow, not a free-roaming agent. Following Anthropic's Building effective agents, the LLM handles language (classifying, writing answers) while routing is plain code. That makes every decision testable and explainable.
Guardrails outside the model. Safety and security rules are OR-ed with the model's output. A model mistake can make FixFlow more cautious but never less, and safety cases are never auto-closed.
Structured outputs. The model must return JSON matching the
Triageschema (a forced tool call on Anthropic, JSON mode on OpenAI). Pydantic rejects anything invalid, and the agent falls back to the offline triager instead of failing.Groundedness check on LLM answers. Testing the live demo showed the model sometimes adds plausible steps that are not in the manual, despite the prompt. Every numbered step is now compared with the cited article (word-stem overlap); if any step is not supported, the LLM reply is discarded, the article's own steps are used, and the trace records it. It is a cheap heuristic: it catches clearly invented steps, not subtle ones.
BM25 instead of a vector database. For about 40 short sections, BM25 is fast, transparent and needs no extra infrastructure. The
Retrieverinterface makes it straightforward to add embeddings later.Confidence threshold. Below 0.35 confidence the agent escalates rather than guesses. The threshold is configurable with
FIXFLOW_CONFIDENCE_THRESHOLD.Evaluation in CI. The build fails if test-set action accuracy drops below 90%, so a change that breaks quality cannot be merged unnoticed.
Project layout
fixflow/
agent.py decision workflow and answers
retrieval.py tokenizer, BM25, inverted index (v1 and v2)
classify.py offline triage and safety rules
llm.py Anthropic and OpenAI clients, guarded LLM triage
tools.py SQLite: warranty, tickets, escalation
catalog.py approved-software catalog
evals.py evaluation harness
api.py FastAPI app
static/ demo web app (index.html)
mcp_server.py MCP server
data/
kb/ 12 troubleshooting articles (Markdown)
devices.csv device and warranty records
software_catalog.csv
eval/tickets.jsonl
tests/ pytest suite, with fake LLM clientsRoadmap
Hybrid retrieval (BM25 + embeddings) and a cross-encoder re-ranker
LLM-as-judge scoring for answer quality, alongside the exact-match metrics
Feedback loop: when a self-served user still opens a ticket, add that case to the eval set
Small web front end in React
License
MIT
Available Tools
5 toolscheck_warrantyA
Look up a device by serial number: model, plan and whether it is still under warranty.
| Name | Required | Description | Default |
|---|---|---|---|
| serial | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. 'Look up' implies a read-only operation and the description names the return fields, but it omits permissions, not-found behavior, and any rate-limit or error details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single efficient sentence with the key resource and return information front-loaded. Every phrase contributes to understanding the tool's purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter lookup with no output schema or annotations, the description adequately explains what the tool does and what it returns. Minor gaps around not-found behavior and serial formatting remain, but they do not block correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clarifies that the serial parameter is a device serial number, but it does not specify format, examples, or validation rules for the serial value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: look up a device by serial number. It also previews the returned fields (model, plan, warranty status), making the tool distinct from siblings like create_ticket or search_manuals, though it does not explicitly name an alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the warranty-status lookup purpose, but there is no explicit guidance on when to use this versus triage_request or search_manuals, and no exclusions or prerequisites are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_ticketC
Open a support ticket. category must be one of the FixFlow categories; it decides the team.
| Name | Required | Description | Default |
|---|---|---|---|
| serial | No | ||
| summary | Yes | ||
| urgency | Yes | ||
| category | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the full burden of behavioral disclosure. It says the tool creates a ticket but never states whether the ticket ID is returned, whether duplicate tickets are prevented, what urgency values are accepted, or what the optional serial is used for — significant gaps for a write operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with the core action front-loaded and no filler. The reference to "FixFlow categories" is unexplained but does not bloat the text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a four-parameter write tool with no annotations, no output schema, and zero schema description coverage, the description is too thin. An agent still cannot determine valid urgency values, the meaning of serial, or what a successful call returns.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across four parameters, so the description must compensate and largely does not. It clarifies category's valid domain and downstream effect ("it decides the team"), but urgency, summary, and serial are left completely undefined, including where the FixFlow category list can be obtained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description pairs a specific verb with a specific resource ("Open a support ticket"), which separates it from read-oriented siblings such as get_ticket and search_manuals. It does not explicitly contrast itself with triage_request, which is the closest ambiguous alternative, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this tool versus triage_request or get_ticket, and no prerequisites are given. The only conditional guidance is the constraint that category must be one of the FixFlow categories, which governs a parameter rather than tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ticketB
Get the status and details of a ticket by its ID (for example FF-1A2B3C4D).
| Name | Required | Description | Default |
|---|---|---|---|
| ticket_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry the behavioral burden. It implies a read-only lookup by saying 'Get' and 'status and details,' but it does not explicitly confirm read-only behavior, describe error handling for missing tickets, or disclose what 'details' includes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no unnecessary wording. It efficiently communicates the operation, resource, lookup key, and an example format.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter lookup, the description is mostly adequate: it names the returned content (status and details) and shows the ID format. However, without annotations or an output schema, it could do more to clarify read-only behavior and failure cases such as an unknown ticket ID.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description needs to compensate. It adds a useful example ticket ID format (FF-1A2B3C4D), which gives more meaning than the bare 'string' schema, but it does not explain ID source or validation constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb-resource pair: 'Get the status and details of a ticket by its ID.' It distinguishes this lookup from create_ticket by implication, but does not explicitly mention the other siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no explicit guidance on when to use this tool versus alternatives such as search_manuals, triage_request, or create_ticket. The by-ID lookup is implied, but there are no when-not-to-use conditions or routing instructions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_manualsA
Search the laptop troubleshooting knowledge base. Returns the best-matching sections with article IDs.
| Name | Required | Description | Default |
|---|---|---|---|
| k | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It discloses that the tool returns best-matching sections with article IDs, but it does not clarify whether the search is read-only, how results are ranked, whether there are result limits, or what type of matching is used.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two tight sentences with no unnecessary wording. The core purpose is front-loaded and easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple and an output schema exists, so the description need not explain return values in detail. Still, the missing parameter semantics and usage guidance leave meaningful gaps for correctly invoking the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It does not explain the required query parameter or what the k parameter controls, leaving the meaning of k entirely undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb (Search) and resource (laptop troubleshooting knowledge base), making the tool's purpose immediately clear. It is also clearly distinguishable from the sibling ticket and warranty tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for finding laptop troubleshooting information, which is useful context. However, it does not explicitly state when to use this tool versus alternatives, nor does it provide any exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
triage_requestB
Run the full FixFlow workflow on a support request: classify it, find the fix, check warranty, then answer it, open a ticket, or escalate it to a person. Returns the decision and the reasons.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| serial | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description carries the full behavioral burden, and it does disclose meaningful side effects: the run may open a ticket or escalate to a human, and it returns a decision plus reasons. It does not say whether a ticket is created on every run or conditionally, whether repeated calls duplicate tickets, what permissions are needed, or what the decision/reason payload looks like.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler, and the workflow scope is front-loaded ahead of the outcome list. The comma-spliced list of branch outcomes is dense but readable; nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a multi-step orchestrator with side effects, zero annotations, no output schema, and undescribed parameters, the definition covers the qualitative shape but omits the operational details an agent needs: what 'serial' does, whether ticket creation is conditional, and what the returned decision reasons contain. Nothing is contradicted, but it is thin for this complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description says nothing about either parameter. 'text' is self-evident from name, but 'serial' is never tied to the 'check warranty' step, so an agent cannot tell from the definition that omitting it disables or degrades warranty checking. The description fails to compensate for the total lack of schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a concrete operation on a concrete resource ('run the full FixFlow workflow on a support request') and enumerates the sub-steps (classify, find fix, check warranty, answer/open ticket/escalate), which implicitly distinguishes it from the narrower siblings search_manuals, check_warranty, and create_ticket. It stops short of explicitly framing itself as the orchestrator that replaces those calls.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the enumerated sub-steps suggest this is the end-to-end entry point, so an agent can infer it should be preferred over chaining the individual siblings. There is no explicit when-to-use statement, no when-NOT-to-use, and no pointer to the sibling tools that perform single steps.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
check_warranty - First observed
create_ticket - First observed
get_ticket - First observed
search_manuals - First observed
triage_request
TDQS
Scored across 5 tools
triage_request is an orchestrator that internally performs classification, manual search, warranty lookup, ticket creation, and escalation, so it overlaps heavily with search_manuals, check_warranty, and create_ticket. The descriptions do signal 'full workflow' vs. individual step, which helps, but agents must decide between one-shot triage and composing primitives with no guidance on when to prefer which.
All five tools follow a clean verb_noun snake_case pattern: triage_request, search_manuals, check_warranty, create_ticket, get_ticket. Verbs are distinct and predictable, and the resource noun is always at the end.
Five tools is well-scoped for a support triage workflow: one orchestrator plus four focused primitives. Each tool earns its place and nothing feels padded or missing at the count level.
Ticket handling is incomplete: you can create and get a ticket but not update, close, comment on, or list tickets, so agents hit dead ends after creation. Similarly, search_manuals returns article IDs but there is no tool to fetch a full article, and escalation only exists implicitly inside triage_request.
Maintenance
Related MCP Connectors
Manage tickets, run agents and workflows, query tables, and search workspace knowledge.
Helpdesk tickets from your AI: find, reply, take, hold, complete — within your own role. OAuth.
AI-native ITSM and ESM platform. resolve IT and HR requests inside Slack and Teams.
Salesforce-grounded retrieval, diagnoses, and a vetted-Force marketplace for MCP clients.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to analyze IT support tickets, categorize urgency, suggest responses, and retrieve statistics via MCP tools.-
- FlicenseNot gradedqualityDmaintenanceMCP server that provides IT support tools to search known incidents, check ticket status, and create ticket drafts, enabling an AI assistant to help users with IT support queries.-
- FlicenseNot gradedqualityCmaintenanceEnables AI clients to access and manage an internal support ticket queue through MCP tools, resources, and prompts, including searching and viewing tickets, adding comments, closing tickets with confirmation, reading knowledge base articles, and viewing queue summaries over OAuth-secured Streamable HTTP.-
- FlicenseNot gradedqualityCmaintenanceEnables IT helpdesk operations such as retrieving user and device information, checking device status, and creating, retrieving, and updating support tickets through MCP tools.-