“Great question! Let’s think through the moving parts.”
That sentence sounds polite. In a coding session, it can be the beginning of failure.
The developer does not need a ceremonial opening. They need to know which file to edit, which command to run, what changed, and how to tell whether the task worked. Instead, the useful action is often buried beneath reassurance, restated context, optional alternatives, and a closing paragraph inviting further questions.
The trending GitHub project i-have-adhd attacks this pattern with a small set of output rules for coding agents: lead with the next action, number multi-step tasks, suppress tangents, restate state, give concrete time estimates, make progress visible, and end with one clear next step.
The project is framed around ADHD-friendly output, but its significance is broader. It exposes a fundamental weakness in AI interface design: language models optimize for plausible, complete prose, while users often need executable state transitions.
This is not an argument that every answer should be short. It is an argument that the shape of an answer should reduce the distance between understanding and action.
The answer can be correct and still be unusable
Consider two responses to the same bug.
The first explains authentication architecture, mentions several possible package versions, warns that tests should be run, and concludes with an offer to provide code. Every sentence may be accurate.
The second says:
Run `npm install jsonwebtoken@latest`, then edit `src/auth.ts:42`.
1. Replace `verifyToken` with the snippet below.
2. Run `npm test -- auth.spec.ts`.
3. If it fails, paste the first failing line.
The second response converts information into a path.
Usability is not identical to correctness. A response also has to support orientation, initiation, execution, error recovery, and completion. If the user cannot find the next action, the answer has failed as an interface even when it succeeded as prose.
Coding agents are interfaces, not essay generators
A coding assistant sits inside an active work loop. The user may be switching between editor, terminal, browser, ticket, and conversation. They are holding file names, error messages, decisions, and unfinished steps in working memory.
The agent’s message enters that overloaded environment.
An essay can be valuable when the goal is learning. During execution, the same essay competes with the task. The user has to extract commands, preserve ordering, remember prerequisites, and infer what success looks like.
A better mental model is that the assistant renders a temporary task interface using text.
type TaskResponse = {
state: "ready" | "blocked" | "in_progress" | "done";
nextAction: Action;
steps?: Step[];
evidence?: Evidence[];
risk?: RiskNotice[];
recovery?: RecoveryPath;
};
Prose still matters. It should serve these interface functions rather than hide them.
Working memory is part of the system budget
Software systems budget CPU, memory, network requests, and tokens. Human working memory is rarely treated as a resource, yet every instruction consumes it.
“Keep the previous caveat in mind while you choose one of the following seven approaches” creates invisible state in the user’s head. If that state falls out of memory, the task can fail.
A text interface can externalize state:
Current state: tests pass; deployment not started.
Decision: use the existing migration, not a new table.
Next action: run the staging deploy command below.
Stop condition: do not continue if schema version is not 184.
The principle is simple: if information is required for the next decision, keep it visible near that decision.
This helps people with attention or memory difficulties, but also helps anyone interrupted, stressed, working in a second language, or returning to a task after a delay.
Action-first does not mean explanation-free
Leading with the action is sometimes misunderstood as removing reasoning.
The useful pattern is progressive disclosure:
Action
-> exact steps
-> verification
-> explanation
-> alternatives and edge cases
The user can begin immediately and read deeper when needed. The explanation remains available, but it no longer blocks the path.
For a high-risk action, the order may change slightly:
Risk: this migration deletes duplicate rows.
Action: create a backup, then run the dry-run command.
Verification: confirm the reported row count.
Only then: run the real migration.
Action-first is not recklessness. The first visible thing should be the next safe decision.
The first action should be small enough to start now
“Refactor the authentication system” is a goal, not an action.
“Open src/auth/session.ts and find refreshSession” is an action.
Large steps create initiation friction because the user must decompose them before doing anything. A good assistant performs that decomposition.
function isActionable(step: Step): boolean {
return step.hasConcreteVerb &&
step.hasTarget &&
step.expectedDurationMinutes <= 15 &&
step.successCondition !== undefined;
}
The fifteen-minute threshold is illustrative, not universal. The design question is whether the step has a clear beginning and observable end.
An instruction can be technically specific and still too large. “Implement OAuth” names a technology but not a next move.
Numbered steps reduce hidden ordering work
Paragraphs make sequence ambiguous. Does the second sentence happen after the first, or is it an alternative? Can tests run before the configuration edit? Which step should be repeated after a failure?
Numbering makes dependency visible.
1. Copy `.env.example` to `.env.local`.
2. Set `DATABASE_URL`.
3. Run `pnpm db:migrate`.
4. Run `pnpm test -- auth`.
Each step should perform one bounded transition. A list item containing three “and then” clauses is still an unstructured workflow.
The assistant can represent dependencies explicitly when the task branches:
steps:
- id: configure
action: create local environment file
- id: migrate
needs: [configure]
- id: test
needs: [migrate]
- id: inspect_failure
if: test.failed
This is not only clearer for humans. It also makes the plan easier for an execution agent to track.
State should be restated because conversations are lossy
Long agent sessions span interruptions, tool calls, context compaction, retries, and user corrections. The visible message may be the only state the user can reliably access.
Restating does not mean repeating the entire history. It means preserving the minimum state needed to continue.
{
"done": [
"reproduced timeout",
"added failing test",
"patched retry loop"
],
"current": "integration test running",
"blockedBy": null,
"next": "inspect retry count in test output"
}
A concise state block prevents the user from reconstructing progress from ten earlier messages.
It also protects against an assistant contradicting itself. If the state says the migration is not applied, a later step should not assume that it is.
Visible progress is functional feedback
Progress indicators are often treated as decoration. In delegated work they answer essential questions: Is the agent still working? Did anything finish? Is it safe to interrupt? What remains?
A useful update reports changed state rather than activity theater.
Bad:
I’m thinking through the issue and exploring several possibilities.
Better:
Completed: reproduced the failure and isolated it to token refresh.
Running now: the focused auth test suite.
Remaining: verify the fix under two concurrent requests.
The second update gives the user control. They can decide whether to wait, redirect, or stop.
Time estimates should name scope and uncertainty
“This may take a while” is almost useless. “About 4 minutes for the focused tests; up to 12 if the integration environment must rebuild” is actionable.
An estimate should be tied to a specific step and updated when evidence changes.
type Estimate = {
step: string;
optimisticMinutes: number;
likelyMinutes: number;
upperBoundMinutes: number;
assumption: string;
};
False precision is not the goal. A range with assumptions is better than confident fiction.
The agent should also distinguish active work from waiting on external systems. “The build is queued; no agent work is occurring until it starts” is honest and helps the user decide whether to switch tasks.
Tangents are expensive because attention has switching costs
Language models are good at generating adjacent advice. A question about one failing test can trigger dependency audits, architecture suggestions, security caveats, style improvements, and career encouragement.
Some of those ideas may be useful later. Presenting them now can prevent the user from finishing the current task.
A relevance filter can classify content:
function include(point: Advice, task: Task): boolean {
if (point.requiredForNextAction) return true;
if (point.preventsLikelyDataLoss) return true;
if (point.explainsCurrentFailure) return true;
return false;
}
Optional improvements can be placed under a short “Later” heading or omitted until requested.
Completeness is not the same as usefulness.
Error messages should preserve momentum
An assistant error can easily become a social performance: apology, explanation, reassurance, and another vague promise.
The user needs four things:
What failed: staging deploy timed out after 10 minutes.
What is safe: no production change was made.
What I know: build 581 completed; release creation did not.
Next action: rerun only the release step with the command below.
Matter-of-fact error reporting reduces shame and uncertainty. It also makes recovery visible.
A good error structure is:
type RecoverableError = {
failedOperation: string;
effectState: "none" | "partial" | "unknown" | "complete";
evidence: string[];
safeNextAction: string;
requiresConfirmation: boolean;
};
The unknown state is important. Pretending an external side effect definitely failed can cause dangerous duplicate retries.
End with one concrete next step
Many AI responses end with a menu:
“I can also explain the architecture, write tests, create documentation, optimize performance, or help with deployment.”
That transfers prioritization back to the user at the moment they expected progress.
A better ending preserves momentum:
Next: run `pnpm test -- auth.spec.ts` and paste the first failing line.
One next step does not eliminate user agency. The user can still choose another direction. It reduces the cost of continuing the most likely path.
Shorter is not always more accessible
A one-line answer can be inaccessible if it omits prerequisites, context, verification, or recovery.
Compare:
Run the migration.
with:
Run `pnpm db:migrate` from the repository root.
Expected result: `Applied 3 migrations`.
If it reports a lock, do not retry; paste the lock owner line.
The second answer is longer and easier to use.
Accessibility is not a character-count target. It is the reduction of unnecessary cognitive work while preserving necessary information.
A list cap is a useful constraint, not a universal law
The project recommends limiting lists. Long lists are difficult to scan and remember, especially when every item appears equally important.
But arbitrary truncation can hide critical steps. The better rule is to limit the active decision surface.
A long procedure can be divided into stages:
Stage 1 — Prepare
1. Back up the database.
2. Confirm schema version.
3. Run the dry-run report.
Stop here and verify the row count before Stage 2.
The user sees only the decisions needed now. Later steps remain available without competing for attention.
Headings are navigation, not decoration
Clear headings let users jump directly to action, explanation, risk, or recovery. They are especially valuable when the response is necessarily long.
A consistent response contract might use:
Outcome
Next action
Steps
How to verify
If it fails
Why this works
Not every answer needs every heading. Consistency helps users predict where information will be.
Cognitive accessibility guidance from the W3C similarly emphasizes clear content, understandable controls, visible structure, and user testing with people who have cognitive and learning disabilities. The lesson for agents is that output design should be tested with real users rather than inferred from developer taste.
The assistant should not diagnose the user
An “ADHD-friendly” output mode can be useful without claiming to know whether a user has ADHD.
The interface should respond to preferences and observable needs: shorter blocks, action-first order, persistent state, fewer choices, concrete time estimates, and visible progress.
It should not infer a diagnosis from behavior, expose a private accessibility preference to unrelated systems, or treat all people with ADHD as having identical needs.
type OutputPreferences = {
actionFirst: boolean;
maxActiveChoices: number;
restateState: boolean;
concreteTimeRanges: boolean;
explanationDepth: "minimal" | "normal" | "deep";
};
Preference-based personalization is safer and more respectful than identity-based assumptions.
Accessibility preferences are sensitive data
If a user requests simplified or ADHD-friendly output, that preference may imply information about cognitive vulnerability. It should not become advertising data, workplace analytics, or a visible public profile label without explicit consent.
The safest default is local or session-scoped storage:
const preferences = {
scope: "device",
sync: false,
visibleToTools: false,
expires: "user-controlled",
};
Tools need the formatting result, not necessarily the reason behind it. A code runner does not need to know that the user selected a cognitive-accessibility mode.
Personalization should minimize disclosure.
Persistence needs a visible off switch
The skill is designed to remain active until the user turns it off. Persistence reduces repetition, but hidden persistence can become surprising when the context changes.
A visible mode indicator helps:
Output mode: Action-first
Change: “normal mode” or “deep explanation mode”
Modes should not silently leak into unrelated agents, evaluations, or automated subprocesses. A preference intended for one conversation can contaminate benchmarks if the evaluation environment inherits it.
Configuration scope should be explicit: message, session, project, device, or account.
One format cannot serve every task
Debugging, learning, design review, incident response, brainstorming, and emotional support have different output needs.
An action-first response is ideal when the next step is known. It may be inappropriate when the user is exploring an ambiguous problem and needs competing models rather than one directive.
The response planner can classify task mode:
function responseMode(intent: Intent): Mode {
switch (intent.kind) {
case "execute": return "action-first";
case "diagnose": return "evidence-first";
case "learn": return "concept-first";
case "decide": return "tradeoff-first";
case "brainstorm": return "divergent";
}
}
Human-centered design means adapting structure to the goal, not enforcing one aesthetic everywhere.
Commands should be copyable and safe
A buried command is hard to find. A prominent command can be dangerous if it is destructive, environment-specific, or incomplete.
Good command presentation includes working directory, assumptions, expected effect, and a stop condition.
From the repository root, run:
`pnpm test -- auth.spec.ts`
Expected: 12 passing tests.
This command does not modify data.
For destructive commands, the response should lead with the risk and resolve exact targets before presenting execution.
Copyability is not permission. The user should understand what the command affects.
Code snippets need insertion context
A correct snippet without a destination creates another search task.
File: `src/auth/verify.ts`
Replace: `verifyToken` function
Keep: existing imports and exported function name
Then run: `pnpm test -- auth.spec.ts`
Diff format can reduce ambiguity:
- return jwt.verify(token, secret)
+ return await verifyJwt(token, { secret, algorithms: ["HS256"] })
The user should know whether to add, replace, or compare. “Use this code” is not an editing instruction.
Success criteria close the loop
An agent often tells the user what to do without explaining how to know it worked.
Every actionable step should have an observable outcome:
action: run focused authentication tests
command: pnpm test -- auth.spec.ts
success:
exit_code: 0
output_contains: "12 passed"
failure_capture:
- first error line
- failing test name
Verification prevents premature completion. It also gives the next assistant turn structured evidence.
“Done” should mean the success condition was observed, not merely that a command was issued.
The response should degrade gracefully under interruption
Users switch windows, attend meetings, lose connection, and return hours later. A message should allow re-entry without rereading the whole conversation.
A resumable response contains a checkpoint:
Checkpoint
- Fixed: refresh-token retry loop
- Verified: unit tests pass
- Not verified: concurrent integration case
- Resume with: `pnpm test -- auth.concurrent.spec.ts`
The checkpoint is valuable even for users without any diagnosed attention difficulty. Interruption is a universal condition of modern work.
Measuring response quality requires task metrics
Traditional language-model evaluation scores correctness, preference, or style. Human-centered agent output needs execution metrics.
Useful measures include:
- time to identify the next action;
- time to begin;
- number of clarification questions;
- skipped-step rate;
- wrong-command rate;
- successful recovery rate;
- completion rate after interruption;
- amount of scrolling before action;
- user confidence calibration;
- retained understanding after completion.
An evaluation record might look like:
{
"task": "repair expired JWT dependency",
"variant": "action-first-v3",
"timeToFirstActionSeconds": 18,
"scrollDistance": 420,
"clarifications": 0,
"completed": true,
"unsafeActions": 0
}
The goal is not maximum brevity. It is successful, safe progress with minimal unnecessary effort.
Accessibility must be tested with diverse users
Designers cannot infer cognitive accessibility only from rules. People vary in reading style, expertise, stress, language, vision, motor ability, and preference.
Some users benefit from fewer words. Others need more explanation to feel safe. Some prefer numbered steps. Others need a diagram. Some want progress messages; others find notifications distracting.
User testing should include people with cognitive and learning disabilities, as well as users working under temporary stress or unfamiliar conditions. A mode called “accessible” that has never been tested with its intended users is only a hypothesis.
The hidden danger of confident action-first output
Putting an action first increases the chance that the user follows it immediately. If the action is wrong, the format amplifies harm.
The response planner needs a confidence and risk gate:
function mayLeadWithCommand(plan: Plan): boolean {
if (plan.destructive) return false;
if (plan.targetIsAmbiguous) return false;
if (plan.requiresMissingContext) return false;
return plan.confidence >= 0.9;
}
When uncertainty is material, lead with the smallest diagnostic action instead:
First, run `git status --short` and paste the output.
I need the exact modified files before suggesting a cleanup command.
Action-first should accelerate safe knowledge gathering, not encourage guessing.
Plain language is not simplified thinking
Clear language is sometimes mistaken for shallow language. Technical precision does not require bureaucratic sentences.
Compare:
The asynchronous operation was unable to reach a state of successful
completion due to an authentication-related condition.
with:
The request failed because the access token expired.
The second version is shorter and more precise. It names the operation, cause, and relevant object.
Plain language also avoids unexplained pronouns and vague references. “Run it again after changing that” forces the user to remember what “it” and “that” mean. Repeating auth.spec.ts and TOKEN_TTL costs a few characters and saves a context lookup.
The goal is not to remove domain vocabulary. Terms such as idempotency, transaction, race condition, and schema migration are useful when they identify exact concepts. The assistant should define unfamiliar terms once, then use them consistently.
Visual hierarchy should reflect decision hierarchy
Markdown gives an agent headings, lists, code blocks, tables, quotes, and emphasis. Using all of them at once creates visual noise.
Formatting should answer three questions at a glance:
- What is the current outcome?
- What should I do next?
- Where do I look if it fails?
A long answer can keep those anchors stable:
## Outcome
The timeout is fixed locally; deployment has not started.
## Next action
Run the focused integration test.
## If it fails
Paste the first error and the reported retry count.
## Explanation
The remaining sections explain the retry race in detail.
Bold text should not become a second heading system. Warning icons should be reserved for real risks. Tables are useful for exact comparisons, but poor for a sequence the user must execute from top to bottom.
The visual layer should make priority visible, not merely make the response look designed.
Adaptive output should not oscillate between styles
An assistant may infer that the user prefers compact answers, then suddenly produce a long tutorial when the topic changes. It may overcorrect after one request for detail and remain verbose for the rest of the project.
Preference adaptation needs stability and explicit scope.
type StyleState = {
baseMode: "action-first" | "balanced" | "deep";
temporaryOverride?: {
mode: "action-first" | "balanced" | "deep";
expiresAfterTurns: number;
};
userConfirmed: boolean;
};
The user should be able to ask “more detail for this explanation” without changing every future response. Likewise, “keep it short today” should not become a permanent disability profile.
A small visible label—Mode: action-first—can make adaptation predictable. The system can offer deeper material without forcing it into the active path: “Detailed reasoning is below” or “Ask for the architecture version.”
Consistency reduces orientation cost. Control preserves agency.
A practical response compiler
Instead of asking the model to improvise style every time, an agent system can compile internal task state into a user-facing response.
function render(state: AgentState, preferences: OutputPreferences): string {
const sections: string[] = [];
sections.push(renderOutcome(state));
sections.push(renderNextSafeAction(state));
if (state.steps.length > 1) {
sections.push(renderNumberedSteps(state.steps));
}
sections.push(renderVerification(state));
if (state.failurePath) {
sections.push(renderRecovery(state.failurePath));
}
if (preferences.explanationDepth !== "minimal") {
sections.push(renderReasoning(state, preferences.explanationDepth));
}
return sections.filter(Boolean).join("\n\n");
}
This makes output structure testable. The team can assert that every executable command has a verification step or that a blocked state names the missing input.
What product teams can learn from the trend
The popularity of a tiny formatting skill is a signal. Users are not only asking for smarter models. They are asking for answers that respect attention, working memory, and task momentum.
Product teams can respond by making state persistent and visible, separating action from explanation, providing exact insertion context, showing meaningful progress, limiting active choices, and allowing users to control output depth.
These improvements should exist at the product layer, not rely entirely on clever prompts. A user should not need a special plugin to make the interface reveal the next step.
Final thought: intelligence includes reducing friction
An assistant that knows the correct answer but hides it under two screens of prose is not fully intelligent in practice. It has solved the domain problem and failed the interface problem.
The lesson of i-have-adhd is not that every response must look identical or that all users need fewer words. The lesson is that response architecture matters. Order matters. Visible state matters. Recovery matters. The next action matters.
Human-centered AI does not merely generate information. It shapes information so a real person, in a real context, can use it without spending additional attention reconstructing the task.
Sometimes the most meaningful improvement to an AI system is not a larger model. It is moving the useful sentence to the top.
Top comments (0)