An agent system for support
A hard customer question. The agent gathered the context. A specialist checked the answer. The customer gave the explanation top marks.
- 2026
- Architecture of the circuit, the agent’s instructions, access to the sources, masking data before it is read, shared memory for the team.
The highest possible score for answering the request and solving an extra problem with a terrific explanation.
To work through a single request, a specialist has to hold several layers at once: the ticket and the correspondence, the customer’s structure — company, project, agent, channel — the bot’s flow and its configuration, the message history, analytics exports, logs.
The context is spread across systems. And what matters in it is not the separate pieces of data but the links: which customer, which agent, which version of the flow and which conversation belong together. On the next similar request part of that path is walked again from the start.
We assembled a shared working circuit. A person states the task in ordinary words — “look into this request”. From there the agent decides for itself which sources it needs and gathers the smallest sufficient set of evidence.
Not “all the data, just in case”. Fixing a piece of copy needs only the current configuration; a disputed conversation needs facts about the request itself; logs are opened last — when the flow and the analytics have not explained the problem.
- a task
- the ticket
- customer and project
- accumulated context
- configuration
- analytics
- logs
- a conclusion
- a draft
- a person
The system tells the confirmed from the assumed — that is its main setting.
When the evidence is not enough, the agent does not invent a cause. It writes down what is established, on what data, which hypotheses are left and which exact step comes next. Finding nothing in one source does not count as an answer.
The final message to the customer stays with the specialist. That is how it runs today: a person takes the agent’s draft and rewrites it in their own way of speaking.
Which points at the next layer. The difference between the draft and the sent text is itself material: the system could learn one person’s editing instead of being asked to “make it sound more human”. That layer is not built yet.
- investigation
- a draft
- the person’s voice
- approval
- sending
A case worked through does not stay in a chat with the assistant. It goes into the customer’s folder: a card of the analysis with its evidence, a snapshot of the configuration with its map, the project notes extended.
The next analysis starts not from general documentation but from what the team already learned about this customer. The more real work goes through the circuit, the more useful its context gets.
- a task
- investigation
- knowledge
- shared memory
- the next analysis
In one analysis the customer complained that the bot greets them again and answers things it should not. The flow is large: 2674 elements in the configuration.
The agent found the exact path — eight nodes from the intent to the handover to an LLM agent — and, at the entry, a condition requiring a value of 1 while the flow has 0 written in it. With that configuration the branch the customer asked about never runs.
Then it exported the configuration again, compared the two exports and showed that 54 elements had drifted between intents, with the cause of the drift not established. It wrote exactly that.
- 2674 elements
- the agent found the right branch and explained the handover between agents
- 0 instead of 1
- the entry condition is never satisfied — visible in the configuration itself
- 54 elements drifted
- two consecutive exports differ; the drift is shown, the cause is not invented
How it works underneath
Four different kinds of evidence. The agent’s job is not to blend them.
The mistake in an analysis is almost always the same one: an observation gets explained with documentation, and the documentation gets checked against logs. So each source carries not only what it gives but also what it cannot prove.
-
configuration
the written logic: what the flow does by its own text
-
data
the observable: what happened in the conversations
-
logs
runtime: what the services did at the moment of the event
-
documentation
the expected semantics: how a feature is meant to work by the platform’s rules
The agent does not walk the sources in order. It takes the smallest set for the question at hand and goes a level deeper only when the previous one has not answered. Fixing copy needs the current configuration. A disputed conversation needs the facts about the request. Only a minority of tasks ever reach the logs.
- a task
- the ticket
- customer and project
- accumulated memory
- configuration
- reports
- SQL
- logs
- a conclusion
- a draft
- a human check
- the repository
The first source of facts is not the subject line but the whole card: the thread, internal comments, timings, who asked and who is handling it, the identifiers everything else is linked by.
Discipline matters here more than volume. Pagination is verified, not assumed: the page number, the total, the batch size, repeats and the owner are all checked. If the walk was cut short, the sample is marked incomplete — that shows up in the result instead of staying an assumption. Comments that could not be read are not evidence that no discussion took place.
- Incompleteness is visible
- a limited walk returns a flag, not a silently shortened list
- The sample is not transactional
- requests change while they are being read; a disputed case is read again
- Read only
- statuses, assignments and the answer to the customer are not changed this way — by design
Then the chain is resolved: request → customer → company → project → agent → channel.
A match by name gives a candidate, not an answer. The final link is confirmed by identifiers and by a source with the date it was checked. That is not a formality: a large customer can have several projects and agents with similar names, and analysing the wrong agent looks convincing right up to the moment it is shown to them.
Once linked, what has accumulated about that customer is read: notes, earlier analyses, saved configuration versions.
The configuration is exported as a set: the logic itself and the map between how an element is written in the configuration and how it is recognised in the data. Every snapshot lands in its own directory with a time, an author, a task and hashes. An old snapshot is never overwritten.
The reason is one quirk: after publication, element identifiers can change. Which means today’s configuration does not explain yesterday’s conversation, however well it seems to fit.
- Current is not historical
- only the snapshot taken then stands in for the configuration of that period
- Exported, edited, published
- three different states, and none of them proves another
- Drift is not hidden
- in one analysis two consecutive exports differed in 54 elements out of 2674 — that stayed in the map’s status
- a historical message
- an element
- the period’s snapshot
- the map
- a node of the flow
Five product exports. The agent orders not all five but the ones that answer the question.
-
execution summary
how many times an element of the flow ran, how many unique chats and conversations went through it
-
message history
what was written, which intent was recognised, the text after preprocessing
-
variable state
the flags and counters of a conversation
-
stop points
which elements conversations end on
-
conversation matrix
which elements ran in each conversation
- Days are cut in UTC
- for a customer’s day the offset is set explicitly, otherwise the window slides
- Conditions are kept alongside
- the period, the zone, the filter and the time of retrieval live with the export
When an aggregate is not enough, the agent goes down to SQL — through the data-source API of Grafana.
The session stays on the specialist’s machine: not in a shared environment, not in a repository, not in a chat with the agent. SQL is read-only: this is production data, not a sandbox.
- a local session
- extraction
- a local client
- the source API
- the production database
The message history gives the time, the chat, the agent, the element of the flow, the sender and the content. That is enough to move from “the bot answered wrong” to a chain somebody can check.
And that is the difference between talking about a bot’s behaviour and proving it: observed production behaviour tied to a specific place in a specific version of the executable flow.
- Messages are not a journal
- having the messages does not mean having the full trace through the flow
- Time does not give order
- identical timestamps do not arrange a sequence
- A chat is not a conversation
- a chat with no confirmed session identifier does not guarantee one conversation
- Coverage is checked
- history is not available for every period; a missing period is written down as a limitation
- Deeper is still a task
- a columnar store sits nearby as a possible source of longer history; its actual coverage is still being explored
- a message
- an agent
- an element
- the saved version
- a node of the flow
Every move to the logs starts from a question the previous layer did not answer.
Logs are not the first step and not a universal answer. They come in when the configuration looks correct, the reports have not explained the observation, SQL has not given enough — or when the problem is plainly runtime: a connector, an external call, a model, delivery.
The search is narrow: a known period, one identifier, one component and a stated hypothesis. Retention is limited and is checked in practice: the working window is measured in tens of hours, not months. For older dates the reports and SQL remain — and that is part of the route, not an annoying limitation.
- the agent
- a local tool
- Kibana
- Elasticsearch
Confluence and Slack are easy to write down as “two more sources”. They answer different questions, and blending them is not allowed.
And separately: silence in a channel does not prove that everything works. An unread channel does not prove that no discussion happened.
- Confluence
- how a feature is meant to work normally: the limits of a channel, an element, a variable, an external call, a model. Expected semantics, not an observation
- Slack
- whether this was discussed, whether there was a known incident or an agreement. Context, not a source of truth about production behaviour
The one place where the circuit writes outward is time tracking. It is built as the pattern for every future write.
Before a write the state is read again and a stale proposal is rejected. A unique identifier on the record makes it impossible to book the same thing twice. If no confirmation came back after a write, that is an undetermined result, not permission to repeat.
The same pattern later carries the answer to the customer: a draft, a check, the action, a verification. Being able to write does not turn into the right to write.
- a proposal
- the boundary of authority
- the action
- reading back
Raw exports do not go into the model’s context as they are. Secrets and tokens, emails and phone numbers, names, addresses and request identifiers are masked. The masking is reversible: the substitutions live in a separate local file, and the original can be restored while that file is intact. It goes neither into a repository nor into a chat.
Reading raw files is blocked by hooks at the level of the agent’s tools: if a file has not been prepared, the read is refused, and the right move is to prepare a copy rather than find another way around. Before the first run against real data, the hooks are tested separately.
Honestly about the boundary: this is a layer that lowers risk, not isolation. It reduces how much sensitive material reaches the model’s context, and claims nothing more.
- a source
- a local file
- masking
- the agent’s context
An investigation does not end in one chat with an assistant. The shared repository takes the customer context and the notes, a separate card of the analysis with its evidence, configuration snapshots and their maps, checkable edits and whatever new turned up along the way.
Everyone works in their own branch, the author of a change is visible, the checks run before anything is merged. Merging a branch does not publish a bot — those are different states too.
- Knowledge lives outside the chat
- the next analysis starts from what the team already found out
- Versions are not overwritten
- old snapshots and notes stay where they are
- a task
- the ticket
- context
- Confluence
- configuration snapshots
- GraphQL reports
- Grafana · PostgreSQL
- Kibana · Elasticsearch
- Slack
- YouGile
- evidence
- a draft
- a human check
- the customer
- memory
The system already runs on real requests, and its result reached a customer.
There will be no percentages of time saved here: nobody measured them. What is listed is what can be checked.
- It is used
- people work through real requests in it
- An analysis across sources
- ticket, customer structure, configuration, analytics, logs — in one task
- The answer reached the customer
- and the customer singled out the quality of the explanation
- An analysis repairs the tool
- along the way two data-reading bugs were found and fixed, 25 local checks
- The knowledge stays
- every analysis adds to the customer’s folder
We automate not a single action but the work around a person.
The system can find context, use tools, carry out part of the process and hand the result back to a person. Support is only the first circuit: the same pattern fits operations, analytics, legal work, internal support — any knowledge work where the answer is assembled from several sources.
How it was put together — the note “Support, filed in a folder” on nikeshin.space.