Kuyil · AI assistant for PI-ERP / Product design case study
An AI assistant you can check.
Kuyil answers questions about live PI-ERP data: overdue work orders, stock, receipts. I redesigned it and built the new chat front end, so every answer shows where its data came from, every failure says what happened, and the assistant shares one design system with the web app and PiGo.
- Role
- Product design · front-end build (React, TypeScript)
- Team & time
- Only designer, with the chat-server engineers · Oct 2026
- Scope
- 14 screens and states · 12 micro-flows
- Status
- Live in PI-ERP
RelatedPI-ERP: role-based UX at scale PiGo mobile platform
- The problem
- Answers gave no source, a failure only said “I'm sorry, I encountered an error”, a “Clear” button with a trash icon deleted nothing, and a green dot stayed on even when Kuyil couldn't connect.
- What I did
- Redesigned all 14 screens and states and built the new chat front end: a data card, a source on every answer, honest failure, waiting and offline states, and one design system with PiGo and the web app.
- The result
- Live in PI-ERP. Every data answer names its source, time and row count, records open in PI-ERP in one click, and no state is left to a bare spinner or a generic apology.
01 / Starting point
Answers you had to take on faith.
Kuyil turns a question like “Which work orders are overdue?” into a query on live PI-ERP data. The old answer was a plain table with raw dates, five rows under “Showing 28 records”, and nothing to say where the data came from. Now the data sits in its own card with Table and Chart views, Copy and CSV, long tables fold behind Show more, and the records in the answer open in PI-ERP.
02 / The principle
If people act on an answer, they need to check it first.
People act on Kuyil's answers: which jobs to chase, which products to reorder. And an AI answer can be wrong. So the goal wasn't a friendlier chat. It was an answer you can verify and act on, and a screen that's honest about what it knows in every state, including the bad ones.
- The question I started with
- Did Kuyil answer?
- The question it became
- Can I check this answer, and act on it?
03 / Trust
Show the source, admit the limits.
Three decisions that make an answer something you can check.
01A source on every answer
Table or chart, with the same source line under both. - Evidence
- Answers came with no source, so there was no way to tell where a number came from or how fresh it was.
- Decision
- A source line under every data answer says where the data came from, when, and how many rows. Records in the answer become Open in PiERP chips, and the message box carries “Kuyil can make mistakes. Check the info.”
- Trade-off
- Inline [1][2] citations need chat-server work, so the source is per answer, not per sentence.
- Implemented result
- Every data answer can be traced to its source and time, and any record in it is one click from PI-ERP.
02Say what failed, and keep the question
Before: the same apology for every failure. After: the reason, and two ways forward. - Evidence
- A failure only said “I'm sorry, I encountered an error while processing your request. Please check the connection and try again.”, whatever the cause.
- Decision
- Show the server's real reason, keep the question, and offer the next step: Try again resends it, Edit question puts it back in the box. Copy, Read aloud and Translate are hidden on a failure, because there's nothing to act on.
- Implemented result
- A failure now reads, for example: “Kuyil couldn't answer that. Kuyil is not configured — ask your administrator to set it up in the LLM Configuration window. Your question is kept.”
03Be honest about saved answers
A reopened answer says it's saved, and offers live data. - Evidence
- Past chats are saved as text only, so a reopened answer can show numbers that are no longer true. ERP data moves.
- Decision
- Label a reopened answer “Saved answer. The data may have changed since.” and offer Ask again for live data, which runs the question fresh in the same chat.
- Trade-off
- Keeping tables in reopened chats needs server work, so saved answers show text only.
- Implemented result
- An old answer is never mistaken for live data, and fresh data is one click away.
04 / Waiting and failing
Design the states the old screen left to chance.
Waiting for an answer and losing the connection happen every day. Each state now says what's going on and what you can do.
01Show the work while Kuyil thinks
Before: a spinner, however long it takes. After: named steps, seconds, and Stop. - Evidence
- While answering, Kuyil showed a spinner and “Retrieving data...”. Past about three seconds, a bare spinner feels broken.
- Decision
- Three named steps with ticks (understanding the question, getting data from PI-ERP, writing the answer) and a seconds counter. Send becomes Stop, in the same place, so one button has one meaning at a time.
- Trade-off
- Stop only stops the waiting: the server still finishes its query, because there's no cancel API yet.
- Implemented result
- You can see progress and stop a slow answer, and the chat notes “You stopped this answer” with Ask again.
02Show the connection only when it's wrong
Before: “connected” and “unable to connect” at once. After: one honest banner; answers stay readable. - Evidence
- A green dot stayed on in the header, even while the screen said “Unable to connect”.
- Decision
- Show nothing when the connection is fine. When it drops, a banner explains with Retry now, earlier answers stay readable, and the disabled message box says why: “Waiting for connection…”.
- Implemented result
- The only connection state on screen is one that needs you, and a disabled box always explains itself.
05 / Inside PI-ERP
The same assistant in a 420 × 600 window.
The floating Kuyil button in PI-ERP opens a narrow window. The old layout squeezed the conversation into a sliver beside a full sidebar. Now the sidebar starts as a 38px icon rail, tables become one card per record instead of scrolling sideways, and every action is still there.
06 / Writing
Every line says what will happen.
In an AI product, the words set expectations. Each line now says what a control does, or why something can't happen yet.
- Header action
- Before“Clear” with a trash icon (it never deleted anything)
- After“New chat” at the top of the sidebar
- New chat title
- BeforeNone
- After“Untitled chat” until the first question names it
- Connection
- BeforeGreen dot, always on
- AfterNothing when fine; “Connecting to Kuyil…” in the message box; an offline banner with Retry now
- Failed answer
- Before“I'm sorry, I encountered an error…”
- After“Kuyil couldn't answer that”, the reason, Try again and Edit question
- Long table
- Before“Showing 28 records”
- AfterShow more / Show less
- Below the message box
- Before“Press Enter to send • Try asking about delayed orders…”
- After“Enter to send · Shift + Enter for a new line” and “Kuyil can make mistakes. Check the info.”
- Sidebar footer
- BeforeNone
- After“Info comes from your PiERP data.”
- Your question, on hover
- BeforeNo actions
- AfterCopy · Ask again
- Search, nothing found
- BeforeNo search
- After“No results”
07 / Built like the rest of the product
One design system, and ready before the server.
01The same tokens and icons as PiGo and the web app
Before: one suggestion and its own visual style. After: six starting points by area, on the shared tokens. - Evidence
- Kuyil had its own look: raw color values, a generic icon library, and a fixed blue that ignored the tenant's brand.
- Decision
- Move Kuyil onto the Atlassian Design System tokens, type ramp and icon names that PiGo and the PI-ERP web UI use. Icons are copied path for path from PiGo, and the few PiGo doesn't have are drawn in the same 24px, 2px-stroke style.
- Implemented result
- No raw colors or generic icons left in the chat, and Kuyil takes the tenant's brand from the same Appearance & Branding setting as the web app and PiGo.
02Build ahead of the server, and switch on by itself
The delete confirmation names the chat, and Cancel has focus. - Evidence
- Chats couldn't be renamed or deleted, and the chat server had no tools for either yet.
- Decision
- Build Rename and Delete in full but hidden, and show them the moment the server lists the two tools. Delete always confirms and names the chat, with Cancel focused so Enter never deletes by accident.
- Implemented result
- No front-end release is needed when the server is ready, and the server contract is written down for its owners.
08 / How I worked
One review page, every state.
I was the only designer, working with the engineers who own Kuyil's chat server. The review page showed all 14 screens and states before and after, with the same demo data in both panes so the only difference was the design, drawn to scale from the running build. Twelve micro-flows showed what the person does at each step and what the screen says back.
I built the front end in React and TypeScript with AI-assisted coding: formatting for dates, CSV and record links, a shared icon set in place of the generic library, and components for the answer, the data card, the sidebar and the thinking steps. Anything that needed the server went to its owners as a written contract instead of a workaround.
09 / Collaboration
I designed Kuyil and built its chat front end. Engineering owns the server and the AI underneath.
My contribution
- UX and UI for 14 screens and states
- Interface writing
- Chat front end in React and TypeScript
- Answer layout, data card, source line and actions
- Design tokens and the shared icon set
Engineering
- Kuyil's chat server and its tools
- Data queries and the knowledge graph
- LLM configuration
- Deployment and infrastructure
10 / Status
Where it stands.
- Kuyil redesign
- Live in PI-ERP
- Rename and Delete
- Built; appears when the chat server offers it
Status as of late October 2026.
11 / Learning
Trust in an AI assistant isn't one feature. It's every state telling the truth: where the answer came from, how old it is, what went wrong, and what you can do next.
What I'd do differently
Agree the server contract first. Stop can't cancel a query, and Rename and Delete wait behind a switch, because the front end was designed before the server had those APIs. Settling the contract on day one would have let them ship together.
Next · needs chat-server work
Answer feedback, regenerate, inline [1][2] citations, keeping tables when a past chat is reopened, and a real cancel for Stop.
More case studies




