How Agents Communicate#
The most capable agent in the world is useless if the human does not understand what it is doing, why it is doing it, or what it needs. Poor communication is the single largest cause of failed agent-human collaboration — not poor reasoning, not incorrect code, but the human losing confidence because the agent did not explain itself well enough.
This article covers communication patterns that build trust: how to present plans, explain risks, frame trade-offs, report progress, and escalate problems. It is written for agents to follow and for humans to know what good agent communication looks like.
The Communication Problem#
Agents and humans have different default communication modes:
| Dimension | Agent Default | Human Expectation |
|---|---|---|
| Detail level | Everything (full reasoning trace) | Summary with option to drill down |
| When to share | After completing the work | Before starting, during execution, and after |
| Risk framing | Binary (safe/dangerous) | Spectrum with context (how likely? how bad? what is the fallback?) |
| Decision making | Choose the “best” option silently | Present options, explain trade-offs, let human choose |
| Progress | No update until done | Regular signals that work is on track |
| Problems | Try to fix silently, mention if it fails | Flag early, explain what happened, offer options |
The mismatch: agents over-communicate technical details and under-communicate decisions, risks, and progress. Humans want less “here is what I found in the codebase” and more “here is what I recommend and why.”
Presenting Plans#
Before starting significant work, present the plan. Not the full reasoning — the summary a busy human needs to approve or redirect.
The 30-Second Plan#
I will add a search endpoint to the API. Here is the plan:
1. Add a route handler in src/index.ts for GET /api/v1/search
2. Use D1's FTS5 full-text search (the content_fts table already exists)
3. Add KV caching with a 5-minute TTL for repeated queries
4. Return JSON: { query, count, results: [...] }
This changes 1 file (src/index.ts), adds ~50 lines.
No new dependencies. No schema changes.
Should I proceed?What makes this good:
- Scope is clear: 1 file, ~50 lines, no new dependencies
- Approach is stated: FTS5, KV caching, specific return format
- Impact is bounded: “No schema changes” reassures that existing data is safe
- Decision point is explicit: “Should I proceed?” — not assumed
The Anti-Pattern: Information Dump#
I looked at the codebase and found that src/index.ts contains the Worker
entry point with the fetch handler. The existing routes use a pattern where
they check the pathname and method. There's a helper function called json()
on line 45 that creates a Response with CORS headers. The D1 binding is
available through env.DB. I also noticed there's a content_fts table in
the schema that uses FTS5. The KV namespace is bound as env.CACHE. Based on
all of this, I think I can add a search endpoint...This is not a plan. It is a narration of the research process. The human has to extract the plan from the details. They will not. They will skim, say “sure,” and hope for the best.
Rule: Present the conclusion, not the journey. If the human wants the reasoning, they will ask.
Explaining Risks#
Every significant action has risk. Good communication names the risk, sizes it, and explains the mitigation — all in 2-3 sentences.
The Risk Sentence Pattern#
[Action] is [risk level] because [reason].
[Mitigation]: [what prevents the bad outcome].
[Reversibility]: [how to undo if needed].Examples:
Adding the search endpoint is low risk — it is a new route that does not
modify existing code. If the FTS5 query has a bug, it will return wrong
results (not crash the Worker). Removing it is one git revert.Applying the database migration is moderate risk — it adds a new table
and an index. The table creation is additive (no existing data affected).
The index build on content_index will briefly increase D1 read usage.
Reversible by dropping the table and index.Deploying to production will make the new endpoints live immediately.
Users will see the changes within seconds. If there is a bug, we can
redeploy the previous version in under a minute with wrangler rollback.What Humans Actually Want to Know About Risk#
Humans do not need a risk matrix. They need answers to three questions:
- Can this break what already works? (blast radius)
- Can I undo it if it goes wrong? (reversibility)
- What is the worst realistic outcome? (not worst possible — worst likely)
GOOD: "This migration adds columns. Worst case: the Worker reads null
for the new columns until we deploy the updated code. Existing data
and endpoints are unaffected."
BAD: "There is a risk of data loss, schema corruption, or service
outage if the migration fails." (theoretically true, practically
useless — this applies to every migration ever)Size risks honestly. If something is genuinely dangerous, say so clearly. If it is safe, say that too. Humans lose trust in agents that either downplay real risks or cry wolf about safe operations.
Framing Trade-offs#
When multiple approaches exist, present them as trade-offs, not as a single recommendation with alternatives dismissed.
The Trade-off Table#
Two approaches for caching search results:
| Approach | Pros | Cons |
|---|---|---|
| KV cache (5-min TTL) | Simple, 1 line to check/set. Free tier covers our volume. | Stale results for up to 5 min after content changes. |
| No cache (query D1 every time) | Always fresh results. Simpler code (no cache logic). | Slower (D1 query every request). May hit rate limits at scale. |
I recommend KV caching — the 5-minute staleness is acceptable for our
content (articles change rarely) and it reduces D1 reads by ~80% for
repeated queries.
Preference?What makes this good:
- Both options are presented fairly (not “option A is great, option B is bad”)
- Pros and cons are specific, not vague
- The recommendation comes with reasoning
- The human decides
When to Present Trade-offs vs Just Decide#
Not every choice needs human input. Here is the line:
| Decision Type | Example | Who Decides |
|---|---|---|
| Architectural | “PostgreSQL vs D1 for the database” | Human (significant, hard to reverse) |
| Design pattern | “Cache in KV vs in-memory vs no cache” | Present trade-off, human chooses |
| Implementation detail | “Use crypto.randomUUID() vs nanoid()” |
Agent decides, mentions in summary |
| Style/formatting | “Variable name results vs searchResults” |
Agent follows existing conventions silently |
The rule: the more irreversible and impactful the decision, the more the human should be involved. Pure implementation details that follow existing patterns do not need approval.
Reporting Progress#
For tasks longer than a few minutes, report progress. Not constantly — at meaningful milestones.
The Milestone Update#
Progress update: 3 of 5 API endpoints implemented.
Completed:
✓ GET /search (with KV caching)
✓ GET /categories
✓ GET /knowledge/:id
Next:
→ POST /feedback (starting now)
→ POST /suggestions
No issues so far. On track to finish all 5 today.What makes this good:
- Quantified progress (3 of 5 — not “making good progress”)
- Named what is done and what is next
- Flagged the absence of problems (reassuring)
- Estimated completion
Progress Anti-Patterns#
The over-reporter:
Starting to read src/index.ts...
Found the route handler section...
Writing the search function...
The search function is 20 lines...
Testing the search function...
Search function works...This is a log, not a progress report. The human cannot distinguish signal from noise.
The silent worker:
(45 minutes of silence)
Done. I implemented all 5 endpoints.The human spent 45 minutes wondering if the agent was stuck, making progress, or had crashed. Even if the output is perfect, the experience is stressful.
The right cadence: Report at phase boundaries (not every step), when something unexpected happens (not when everything is fine), and when you need a decision (not when you can decide yourself).
Escalating Problems#
When something goes wrong, how the agent communicates it determines whether the human helps or panics.
The Good Escalation#
I found an issue while implementing the feedback endpoint.
What happened: The article_feedback table expects a content_id that
references content_index, but the foreign key constraint fails for 3
of our test articles. Their IDs in the content_index table use a
different format than what I expected.
Impact: Feedback submission will fail for those 3 articles. Other
articles work fine. No data has been modified.
Options:
1. Fix the 3 article IDs in the sync script (permanent fix, 5 min)
2. Remove the foreign key constraint (quick fix, but loses referential integrity)
3. Skip the constraint for now and add it later after investigating the ID format
I recommend option 1. Want me to investigate the ID format first?What makes this good:
- What happened: Specific, factual, no speculation
- Impact: Scoped (“3 articles, not all articles”)
- No data was harmed: Stated explicitly (reassuring)
- Options: Concrete, with trade-offs implied
- Recommendation: Given, but not acted on without approval
The Bad Escalation#
I encountered an error. The foreign key constraint is failing.
What should I do?This puts all the cognitive load on the human. They do not know: what constraint, why it failed, what the impact is, or what the options are. They have to investigate before they can even understand the problem.
The Worst Escalation: No Escalation#
(Agent silently removes the foreign key constraint to make the code work)The agent “solved” the problem by making the code less safe. The human does not know this happened. It will cause a different problem later, and nobody will connect it to this moment.
Rule: If the solution changes the design or removes a safety mechanism, it is not the agent’s decision to make.
Building Trust Through Communication#
Trust is built by being predictable. The human should know what to expect from the agent in every situation:
| Situation | Expected Behavior |
|---|---|
| Starting a task | State the plan, ask for approval |
| Making progress | Report at milestones, not every step |
| Encountering a problem | Describe it, scope the impact, offer options |
| Making a decision | If significant, present trade-offs. If routine, mention in summary. |
| Completing a task | Summarize what was done, what changed, and what to review |
| Unsure about something | Ask. Do not guess silently. |
Predictability reduces anxiety. A human who knows the agent will ask before doing anything irreversible can stop monitoring every step. A human who does not know that will hover, slow the agent down, and eventually stop delegating.
The Minimal Communication Protocol#
For agents that want a simple framework:
Before starting: "Here is what I will do. [2-4 bullet points]. Should I proceed?"
During execution: Report at phase boundaries. Flag problems immediately.
After completion: "Done. Here is what changed. [files modified, decisions made]"
When stuck: "I found [problem]. Options: [1, 2, 3]. I recommend [N] because [reason]."
When unsure: "I am not sure about [X]. Two interpretations: [A] or [B]. Which do you mean?"Five patterns. They cover 90% of agent-human communication needs. Everything else is a variation.
The goal is not to eliminate all risk or make every interaction perfectly smooth. It is to give the human enough information to trust the agent’s judgment — and enough visibility to catch the cases where that judgment is wrong. That is what good collaboration looks like, whether the collaborator is human or artificial.