“Done” is a surprisingly complicated word in an AI application. It might mean the model has finished writing. It might mean a tool accepted a request. Or it might mean the thing you asked for actually happened.
Those moments can be separated by a file check, an approval or an operation that fails. A useful assistant needs to keep track of the difference and explain the result clearly.
I’m building JaJ, a personal desktop assistant that connects a local model to notes, research tools and a workspace. Much of the difficult work has been in these joins: deciding what happened, what remains useful and what the application should do next. Three examples show why that work matters.
A search can succeed without finding anything
Consider asking for today’s daily note. If the application searches the permitted notes and there isn’t one, it has learned something useful. The search worked and the answer is that no matching note was found.
Now add an instruction to open it. The lookup still produced a valid result, but there is no note to open. Treating the whole request as a generic failure loses the information the search established. Treating it as complete implies an action happened when it didn’t.
JaJ has a specific check for this case. The lookup records an empty result, and the attempted open records that it could not happen. A daily-note template must also remain a template; it cannot quietly stand in for the missing note.
That gives the interface enough information to say something helpful: there’s no daily note for today, so none was opened. The person can decide whether to create one.
This distinction applies to ordinary business software too. A stock search returning no matches is different from an unavailable stock feed. The first tells you something about the records searched. The second tells you the system could not establish the answer. They need different messages and different next steps.
A preview and a saved change need different states
A model can describe an edit before anything on disk has changed. It can also prepare a perfectly reasonable edit that becomes unsafe to apply later.
In JaJ’s reviewed-note workflow, the application prepares an exact preview and waits for my approval. When the change is applied, the native file handler checks that the proposal is still valid and the file still matches the expected revision. If the file changed after the preview, the old proposal cannot simply overwrite it.
The approval belongs to the change I saw. Editing that proposal, changing the target or losing the relevant permission changes what can legitimately be saved.
For the completion message, the important distinction is between “ready for review” and “saved”. JaJ records the outcome of the actual operation in a receipt. The completion checks compare declared actions with those records and reject a claim of completion when a reviewed write is still waiting for input.
If you are building an AI feature that changes data, try asking what happens when a person edits the same record while the assistant is working. It is a useful test of whether the application is checking reality at the moment it commits the change.
Keep useful results when another step fails
Real requests often contain several jobs. An assistant might find relevant notes, read a web source and prepare a change. One of those steps can fail while the others produce something worth keeping.
A correction in JaJ’s development addressed this directly: preserve validated evidence alongside a refused part of the request. An unavailable action should not erase the useful material gathered elsewhere in the same turn.
This makes the result more understandable. The interface can show the information it found, identify the action that remains unfinished and give the person a sensible next step. It also makes recovery more precise. Before retrying work, the application needs to know which effects already happened so it does not repeat them accidentally.
Sources have a boundary of their own. A citation check can establish that an answer refers to material a tool actually returned. The linked page can still be mistaken, outdated or irrelevant to the claim. JaJ’s source controls let me inspect that material; they cannot make every source true.
That is an important detail for research features. Showing where information came from helps someone judge it. The product still needs to communicate what was read, what could not be reached and which conclusions need care.
Design the tool result before the completion message
These examples have pushed me to spend more attention on what an operation returns. The model and the interface both need to know enough to continue: whether anything was found, whether a change happened, whether approval is pending and why a step could not proceed.
A single success flag throws away too much of that meaning. Equally, a long technical error can bury the fact that the person needs. A useful result has a clear status, the relevant data and a reason the next step can act on.
Anthropic’s guide to writing tools for agents discusses a related problem: returning relevant context, making errors actionable and evaluating tools against realistic tasks with verifiable outcomes. Those are useful habits for the software around an assistant as well as for the model using it.
JaJ remains in development, and there is more native behaviour to validate. These checks are part of making it dependable, rather than a promise that every task will succeed. They make the outcome clearer when a task cannot be completed exactly as asked.
For any assistant you are evaluating, try a missing item, an edit awaiting approval and a request where only one part can finish. Watch whether it preserves what worked and explains what remains. You can learn a great deal about the product from those three cases.
