Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
158393 stories
·
33 followers

AsyncAPI Code Generation with Corvus: Filtering

1 Share

At endjin, we maintain Corvus.JsonSchema, and in the previous post we looked at durability and message resumption across different transports.

Now let's look at what happens when your messaging spec grows beyond a handful of channels - and why generating everything is rarely what you actually want.

Why filtering matters for messaging

Event-driven architectures tend to grow. What starts as three channels for a streetlights demo becomes fifty channels spanning order processing, inventory updates, payment notifications, shipping events, and audit logs. And unlike HTTP APIs (where a large spec means a large client library you can mostly ignore), messaging is different. Generated consumers subscribe to channels. If you generate everything, you're subscribing to everything, which means your service receives messages it has no business processing.

Even if you only generate producers, a monolithic generation pass gives you types and channel resolution code for every channel in the spec. That's code to compile, code to maintain, and code that obscures the actual messaging boundaries of your service.

What you want is a clean boundary: this service produces to these channels and consumes from those channels, and the generated code reflects exactly that scope.

Channel filtering

The --include-channel and --exclude-channel options let you select which channels to generate code for:

# Generate only the command channels
corvusjson asyncapi-generate streetlights.json \
    --rootNamespace Streetlights.Commands \
    --outputPath ./Generated \
    --mode producer \
    --include-channel "smartylighting.streetlights.*.turn.*"

# Generate everything except internal audit channels
corvusjson asyncapi-generate events.json \
    --rootNamespace MyApp.Events \
    --outputPath ./Generated \
    --exclude-channel "internal.audit.**"

Channel patterns use glob syntax: * matches within a single segment (between dots), and ** matches across multiple segments. This aligns with how most organisations structure their channel naming hierarchies.

As with OpenAPI path filtering, the generated code is self-contained. Payload schemas referenced by the filtered channels are included regardless of whether other channels also reference them. You always get a compilable output.

Filtering by operation tags

When your spec uses tags to classify operations by domain, you can filter on those directly:

# Generate only operations tagged 'payments'
corvusjson asyncapi-generate platform-events.json \
    --rootNamespace MyApp.Payments.Events \
    --outputPath ./Generated \
    --tag payments

This is particularly useful for specs where the channel naming convention doesn't neatly separate domains, but the tags do. Some organisations tag operations by owning team, by business capability, or by deployment boundary. All of these make good filter criteria.

Previewing the selection

The asyncapi-show command accepts the same filter options, letting you see what will be generated before committing to a generation pass:

# See everything in the spec
corvusjson asyncapi-show platform-events.json

# Preview what a channel filter selects
corvusjson asyncapi-show platform-events.json \
    --include-channel "orders.**"

The output shows the channel tree with operations and message types:

Platform Events v2.1.0 (AsyncAPI 3.0)

Operations (3 of 14)
├── orders.created
│   └── SEND orderCreated - New order placed (1 msg)
├── orders.{orderId}.updated
│   └── SEND orderUpdated - Order status changed (1 msg)
└── orders.{orderId}.cancelled
    └── SEND orderCancelled - Order cancelled by customer (1 msg)

This preview-then-generate workflow is the same pattern as the OpenAPI series. It avoids wasted cycles when you're iterating on the right filter expression.

Splitting a spec by bounded context

The most compelling use of filtering is carving a large shared spec into domain-specific generation targets. Consider a platform events spec that covers ordering, payments, shipping, and notifications:

# Order service - produces order events, consumes payment confirmations
corvusjson asyncapi-generate platform-events.json \
    --rootNamespace Orders.Events \
    --outputPath ./Generated/Orders \
    --mode producer \
    --include-channel "orders.**"

corvusjson asyncapi-generate platform-events.json \
    --rootNamespace Orders.Events \
    --outputPath ./Generated/Orders \
    --mode consumer \
    --include-channel "payments.confirmed,payments.failed"

# Payment service - consumes order events, produces payment confirmations
corvusjson asyncapi-generate platform-events.json \
    --rootNamespace Payments.Events \
    --outputPath ./Generated/Payments \
    --mode consumer \
    --include-channel "orders.created"

corvusjson asyncapi-generate platform-events.json \
    --rootNamespace Payments.Events \
    --outputPath ./Generated/Payments \
    --mode producer \
    --include-channel "payments.**"

Each service gets exactly the producers and consumers it needs. The generated code documents the service's messaging contract explicitly. You can look at what's generated and know precisely which channels this service publishes to and subscribes on.

This also means that regenerating one service's generated code doesn't touch another service. Teams can regenerate independently, and the spec remains the shared source of truth.

Combining mode and channel filters

Notice in the example above that we combine --mode (producer vs. consumer) with --include-channel. This is deliberate. A service might produce to orders.created and consume from payments.confirmed - the same spec, but different roles on different channels.

Running the generator twice (once for producer channels, once for consumer channels) into the same output directory composes correctly. The lock file tracks each generation pass independently, so you can also run them from separate build steps or CI jobs if that suits your workflow.

When to filter

For a small spec with a handful of channels, filtering is unnecessary overhead. But it becomes valuable in several situations:

  • Platform event buses where a single AsyncAPI spec describes the entire organisation's event taxonomy and each service participates in only a subset
  • Shared specs across teams where each team owns different channels and wants to generate only their portion
  • Incremental migration where you're adding typed messaging to an existing system one domain at a time
  • Large IoT deployments where the spec describes hundreds of device telemetry channels but your analytics service only cares about a specific device class

For the complete filtering reference, see the AsyncAPI documentation on corvus-oss.org.

In the next post, we'll look at testing - using the in-memory transport to exercise your producers, consumers, and handlers without a running broker.



Read the whole story
alvinashcraft
just a second ago
reply
Pennsylvania, USA
Share this story
Delete

The Disappearing Senior: AI and Entry Level Jobs

1 Share

Everyone is arguing about AI and entry level jobs. Almost nobody is watching the other end of the ladder.

The Disappearing Senior: AI and Entry Level Jobs ladder-missing-rungs

A few days ago I wrote about a young developer who cannot get past the first interview and cannot tell whether he got worse or the door got narrower. I have not stopped thinking about him. The conversation about AI and entry level jobs is loud, crowded, and mostly correct. The junior work is gone because the machine does it in eight seconds and does not ask about health insurance. But there is a second thing happening at the same time, quietly, at the other end of the ladder, and almost nobody is saying it out loud. So I will.

A quick note. The people in this piece are composites, blended and reshaped from twenty five years of my own work and the lives of people close to me. Nothing here refers to any specific person, employer, client, or company. This is a personal reflection and nothing more.

Nobody Was Ever Made Senior by Approving Things

Think about how you actually got good. Not the story you tell in interviews. The real one.

You got good by being wrong in public, over and over, on things small enough that nobody got hurt. You shipped the thing that looked fine. It was not fine. Somebody older sighed, showed you why, and you felt that particular hot flush of embarrassment that welds a lesson permanently into your bones. Then you did it again three months later in a slightly different costume.

That is the whole training program. It is not elegant. It is a scar collection.

Seniority is not a rank. It is the accumulated memory of every way you have personally made a mess.

Here is the uncomfortable part. All of that learning happened inside exactly the work we just handed to the machine. The boring first draft. The report nobody wanted to build. The tedious middle. That was not filler. That was school, and we just closed the school and kept the diplomas.

What Happens to a Senior Who Stops Doing the Middle

The Disappearing Senior: AI and Entry Level Jobs looks-good-to-me

Now watch what a good senior person’s day looks like this year.

The machine drafts. They approve. The machine drafts again. They approve again. And here is the thing, they approve well. For a while. Their judgment is sharp because it was forged in a world where they had to build the thing themselves before they could have an opinion about it.

But that world is not running anymore, and judgment is not a diploma. It is a muscle, and muscles are appallingly honest about neglect.

So the approvals get a little faster. A little softer. The comment that used to be four paragraphs becomes two lines. Then it becomes looks good to me. Nobody notices, because nothing goes wrong. Nothing goes wrong for a long time. That is the entire trap.

Then one ordinary Thursday, the thing they wave through is wrong in a way the version of them from two years ago would have caught in four seconds. Not two hours. Four seconds. It would have jumped off the screen and grabbed them by the collar.

The scary moment is not when a senior person cannot find the bug. It is the first time they look straight at it and feel nothing.

The Query That Ran Fine

Let me put this in a room I know well.

A team asks the machine for a query. The query comes back looking confident and well dressed. They run it. It returns rows. The rows look plausible. Everybody nods and ships it.

Nobody in that room read the execution plan, which is just the server’s own honest note explaining how it plans to go get your data. Nobody noticed it had decided to read the entire table forty thousand times, because on a small test set that costs nothing and on Monday morning it costs everything.

Two years ago that team had someone who would have opened the plan out of pure reflex. That person is still on the team. They just have not opened one in a while, and reflexes are use it or lose it, same as everything else your body knows how to do.

But We Have Done This Before, Haven’t We

Here is the fair objection, and I want to give it real room, because I have heard it from people I respect.

We panicked about the compiler. We panicked about the IDE. We panicked when everyone started copying answers off the internet instead of reading the manual. Every one of those tools removed drudgery, and the sky stayed up. Older engineers grumbled, younger engineers shipped, and the world kept turning. Why is this different?

I have thought about it a lot, and I think it comes down to one distinction.

Every earlier tool removed the typing. This one removes the reasoning. The compiler saved you from writing machine code, but you still had to decide what the program should do and why. Stack Overflow gave you a snippet, but you still had to figure out whether it applied to your mess, which meant understanding your mess.

The new tool hands you the finished decision, already argued, already formatted, sounding certain. And reasoning was the exact place where all the learning used to live.

Autocomplete made typing cheaper. This makes thinking optional. Those are not the same event.

I could be wrong about this. People were wrong about the calculator, and they were extremely confident while being wrong. But the calculator never told anyone it was sure.

The Math Nobody Wants to Do

The Disappearing Senior: AI and Entry Level Jobs where-do-they-come-from

Put the two halves together and the picture gets uncomfortable fast.

The bottom rung is gone, so no new seniors are being manufactured. And the people currently holding the title are slowly being deskilled by the same tool that removed the rung. One supply line is cut, and the existing stock has a quiet expiration date nobody printed on the box.

Ten years from now, somebody is going to stand in a very expensive meeting and ask where all the people who can actually tell went. And the honest answer is going to be that we stopped making them in 2025 and nobody filed a report about it, because nothing broke that quarter.

Every quarter it does not break, the decision looks smarter. That is what makes it so hard to argue against.

What I Am Actually Doing About It

I am not going to hand you a five point framework and pretend I have this solved. I do not. But here is what I have changed in my own week, and what I have watched work on real teams.

Do one thing the hard way, on purpose, every week. Not everything. One thing. Write the query yourself before you ask. Read the plan before you accept the fix. It is the professional equivalent of taking the stairs, and it works for exactly the same reason.

Make the machine defend itself. Do not ask for the answer. Ask why the other three options are worse. A confident answer is easy to manufacture. A defended answer makes the thin spots visible, and if it cannot defend it, you have just learned something free.

Keep a wrong list. Every time the tool was confidently wrong, write down one line: what it said, what was true, how you caught it. After a month you will have a personal map of where it lies to you specifically, in your domain. Nobody else can write that document for you.

Give the juniors the work you now find boring. This is the one that costs you something real, and it is the one that matters. The boring work was never boring. It was the school. If you hand all of it to the machine because it is cheaper, you have optimized this quarter and quietly mortgaged the decade.

Notice the four second test. If you look at something and feel nothing, sit with that. That flatness is information. It is the closest thing to an early warning system you are going to get.

Nobody Is Coming to Fix This For You

There is no policy landing next quarter that solves this. No company is going to voluntarily pay to train juniors it does not need in order to protect a supply of seniors it will not need for ten years. That is not villainy. That is just how budgets work, and every one of those decisions is defensible on its own.

Which means the maintenance is yours. Personally. Deliberately. On a Tuesday, when nothing is on fire and there is no reason to bother.

That is genuinely annoying, and I wish I had something warmer to tell you. But I would rather say the true thing than the comfortable one.

I have been chasing this question, what is actually left for a person once the machine can do the task, for a couple of years now, and it turned into thirty short essays and a book called AI: Nobody’s in There: But we’re still in here. The Disappearing Junior is one of the chapters. This piece is the part I only understood after the book was already printed, which is either bad planning or proof that I am still learning. Every essay is free to read at pinaldave.com, and there is a paperback on Amazon if you would rather hold something real.

So the ladder is missing its bottom rung, and the people standing at the top are quietly forgetting how they climbed. Both of those are fixable, but only by somebody who noticed. Now you have.

The risk was never that AI would replace your senior people. It is that it will quietly stop making any new ones.

Reference: Pinal Dave (https://blog.sqlauthority.com/), X

First appeared on The Disappearing Senior: AI and Entry Level Jobs

Read the whole story
alvinashcraft
23 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

10 Dialogue Mistakes Writers Make (And How To Fix Them)

1 Share

Good dialogue makes characters come alive. Learn the 10 mistakes writers should avoid and use our infographic to create stronger, more natural conversations.

Writing good dialogue can be difficult. Characters speak in stories, but they do not speak exactly like real people. Fictional dialogue needs to feel natural while also revealing character, creating conflict, and moving the story forward.

Pay special attention to your four main characters. Your protagonist, antagonist, confidant, and love interest should each have a distinct voice. Their vocabulary, speech patterns, and rhythms should help readers understand who they are.

Writers know that every conversation needs a purpose. We need to make every exchange count, ensure our characters do not all sound the same, and remove unnecessary dialogue that slows the story down.

In this post, we look at some of the most common dialogue mistakes beginner writers make. Avoid these errors, and your dialogue will become more professional, natural, and reader-friendly.

10 Dialogue Mistakes Writers Make (And How To Fix Them)

1. Stilted Exchanges

Your dialogue may not sound natural. This is one of the most common mistakes made by first-time novelists. Read your dialogue aloud and ask yourself: does this sound like something a real person would say? Have you included contractions? When we speak, we usually say ‘I’ll’ rather than ‘I will’, and ‘can’t’ rather than ‘cannot’. Details like this can make dialogue feel more authentic.

Example:
❌ Stilted: ‘I am extremely pleased to see you. I have been waiting for two hours.’
✅ More natural: ‘I’m glad you’re here. I’ve been waiting for two hours.’

2. Similar Voices

Make sure each character has a distinct voice. They should have different patterns of speech, vocabulary choices, and ways of expressing themselves. A character’s voice can reveal important details about their background, education, personality, and level of self-awareness. If every character sounds the same, readers struggle to tell them apart.

Example:
❌ Similar voices:
‘I think we should leave now. It is getting late.’
‘Should we leave now? It is getting late.’
✅ Distinct voices:
‘Let’s go. Now.’
‘I’d rather leave before it gets dark.’

3. Small Talk

Small talk is often filler dialogue. It does not advance the plot or enhance our understanding of the characters. Sometimes writers include it because they feel characters have not spoken for a while, or because they want to create white space on the page. Ask yourself: is this conversation serving the reader? Good dialogue should reveal emotions, expose motivations, create tension, or prompt action. If it does none of these things, it may not belong in the story.

Example:
❌ Filler:
‘Lovely weather.’
‘Yes, it is.’
‘Looks like rain tomorrow.’
✅ With conflict:
‘Lovely weather.’
‘Funny. You only smile when you’re about to ask for money.’

4. Exposition

Exposition happens when a character explains a large amount of information in dialogue. This is one of the worst examples of telling rather than showing. Sometimes writers need to share backstory or important details, and they use a character to deliver information instead of weaving it naturally into the story. Avoid making your characters sound like they are explaining the plot to the reader. Let information emerge through conflict, action, and meaningful conversations.

Example:
❌ Too much exposition
‘As you know, we’ve worked together for ten years since your father hired us after university.’
✅ More natural dialogue
‘Ten years.’
‘Don’t remind me.’
‘You still owe me for my first week’s wages.’

5. Using Names In Dialogue

Most people do not constantly use each other’s names when they speak. We usually say someone’s name when we want to get their attention: ‘Jack! We’re over here!’ Or when we want to make a point: ‘I warned you to stop lying, Dylan.’ Using a character’s name too often can make dialogue sound unnatural. It can even make your character sound like a salesperson at a convention. Use names when they have a purpose, not simply to remind readers who is speaking.

Example:
❌ Too many names
‘Sarah, can you pass me the file?’
‘Of course, Michael.’
‘Thank you, Sarah.’
✅ More effective
‘Sarah, can you pass me the file?’
‘Sure.’
‘Thanks.’

6. Not Using ‘Said’

Writers often worry that they use ‘said’ too often. They replace it with verbs like ‘shouted’, ‘stuttered’, ‘breathed’, ‘exclaimed’, ‘cried’, ‘mused’, ‘whispered’, ‘stammered’, ‘uttered’, ‘insinuated’, or ‘hesitated’. Most of the time, ‘said’ works perfectly. Readers barely notice it, which allows them to focus on the character’s words. Use stronger dialogue tags sparingly. Your characters’ words, actions, and body language should reveal their emotions and intentions.

Example:
❌ Too many synonyms for said
‘I don’t believe you!’ she exclaimed angrily.
‘It’s true,’ he protested desperately.
✅ More effective
‘I don’t believe you,’ she said.
He met her eyes. ‘It’s true.’

7. Forgotten Dialogue Tags

A dialogue tag identifies who is speaking, such as ‘he said’ or ‘she said’. If readers have to stop and work out who is talking, you need to include more dialogue tags. However, avoid filling every line of dialogue with them. Too many tags can clutter the page and distract from the conversation. Find a balance between clarity and flow. [Also avoid relying too heavily on adverbial dialogue tags. Don’t write: ‘You are wrong,’ she said angrily. Rather show the anger through the character’s words and actions.]

Example:
❌ Less effective
‘Where are the keys?’
‘I haven’t seen them.’
‘You had them yesterday.’
‘Did I?’
Readers may struggle to work out who is speaking.
✅ More effective
‘Where are the keys?’ Ben asked.
‘I haven’t seen them,’ Lucy said.
‘You had them yesterday.’
Lucy frowned. ‘Did I?’
A few well-placed tags keep readers oriented.

8. Incorrect Dialogue Punctuation

Incorrect punctuation can confuse readers and interrupt the flow of your story. Use quotation marks correctly, decide on your preferred dialogue format, and apply it consistently throughout your manuscript. Small punctuation mistakes can distract readers from an otherwise strong conversation.

Example:
❌ Incorrect punctuation
‘I’ll meet you outside.’ She said.
✅ Correct punctuation
‘I’ll meet you outside,’ she said.
Dialogue tags are not new sentences, so ‘she’ should not begin with a capital letter.

9. Unimportant Conversations

Some conversations contain information that may be necessary but do not need to appear as dialogue. For example, if readers only need to know that a character will return on Monday, you may not need an entire conversation to reveal this information. Ask yourself whether the exchange creates friction, tension, reveals character, or moves the story forward. If it does not, consider removing it or finding another way to share the information.

Example:
❌ Not necessary
‘I’ll see you on Monday.’
‘At nine?’
‘Yes.’
‘Are you sure?’
‘Yes.’
✅ More effective
He arranged to meet her at nine on Monday morning.

10. Too Much Talk

Sometimes silence can be more powerful than words. The things characters choose not to say can reveal more than what they do say. There are moments when a character has no words powerful enough to express their feelings, or when they are unable or unwilling to speak. Use silence carefully. When used at the right moment, it can create some of the most memorable scenes in fiction.

Example:
❌ Talking too much
‘I’m disappointed because I trusted you, and now I’m angry and upset about what you’ve done.’
✅ More effective
‘I trusted you.’
Silence.
‘That was my mistake.’

Dialogue Mistakes Infographic

Would you prefer a quick reference guide? We’ve also created an infographic that summarises these dialogue mistakes and shows you how to avoid them. Save it, share it, and use it as a reminder when editing your own conversations.

10 Dialogue Mistakes Writers Make (And How To Fix Them)

Five Exercises To Help You Avoid These Dialogue Errors

  1. Eavesdrop. Listen to real conversations to understand how differently people speak. Some people use short statements or fragments. Others speak in long, carefully structured sentences. Pay attention to vocabulary, rhythm, and the way people express emotions.
  2. Ask five different people the same question. Ask five different people the same question and compare their responses. Notice the different words they use, the details they include, and the ways they express their thoughts. This is a useful exercise for creating distinct character voices.
  3. Write dialogue-only scenes. Write a scene using only dialogue. This forces you to focus on making each character sound unique and helps you identify when different voices are too similar.
  4. Tell a story. Write a scene where one character tells another character a story. Make sure the listener is engaged and only interrupts when necessary. Use the conversation to reveal personality, emotions, and relationships.
  5. Silence. Write a scene where one character should speak but cannot or will not. Explore what happens when emotions, fear, anger, or uncertainty prevent someone from saying what they want to say.

The Last Word

Good dialogue is about more than making characters talk. It reveals personality, creates conflict, moves the story forward, and helps readers connect with your characters. By avoiding these common dialogue mistakes and practising the techniques that make conversations feel natural, you can write dialogue that brings your stories to life.

Image by Foundry Co from Pixabay


by Amanda Patterson
© Amanda Patterson

More posts from Amanda:

  1. 5 Instances When You Need To Tell (Not Show) In Your Writing
  2. What Is A Sequel In Story Structure? A Writer’s Guide
  3. What Is A Scene In Story Structure? A Writer’s Guide
  4. How To Write A Gripping Novel: 5 Essential Tips
  5. How Many Words Should A Novel Be? A Writer’s Guide To Word Counts
  6. What Is A Novel Outline? 5 Strong Reasons To Outline Your Novel Before You Start Writing
  7. What Is A Good Daily Word Count? Lessons From 39 Famous Authors
  8. 10 Life-Changing Benefits Of Reading More Books
  9. The Author’s Promise: The Two Things Every Writer Owes Their Reader
  10. Why Every Story Needs Consequences

Top Tip: Sign up for our free daily writing links.

The post 10 Dialogue Mistakes Writers Make (And How To Fix Them) appeared first on Writers Write.

Read the whole story
alvinashcraft
37 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Daily Reading List – July 29, 2026 (#835)

1 Share

Busy morning, quiet afternoon. I love having those moments to clear out the inbox, spend time reviewing docs, and even writing a blog post (for tomorrow). Do you freeze when you have an open afternoon without meetings?

[article] How much can you delegate to agents? Is it easy to check? Is it cheap to undo? Ask yourself these questions (and see this flowchart) to help decide how much autonomy you should give your agent.

[blog] Eval Is Evil: How to Safely Execute Untrusted AI Code with Cloud Run sandboxes and ADK. Running injected scripts in your app? Fun for demos, dangerous for real life. This post looks at how to sandbox untrusted code.

[blog] We Killed Reading the Same Way We Caused the Obesity Epidemic. Reading is so good for you. We’ve rigged the game against ourselves, but this post offers a handful of ways to reset.

[blog] Why care about programming languages. It’s not about the syntax; it’s about the deep ideas about computation manifested in these languages.

[blog] Automated pull request reviews with Gemini Managed Agents. Nice example of using these fully managed agents.

[blog] Gameplay Before Strategy. Caught up (frozen?) in high-level grand strategy, but missing the feel that comes from gameplay? Help your team stop hurting themselves, and then aim bigger.

[site] Superlogical: We are building the multiplexer for all work. New startup from Mitchell, co-creator of Hashicorp. Looks like he’s solving a very relevant problem.

[blog] Finally — Hard Caps to Limit Your Google Cloud Spend. Spending caps, in action. Lower your anxiety about finding out too late about spiking usage.

[article] Target SVP says its real AI moat isn’t the models — it’s everything built around them. If the model itself is your moat, I think you made a mistake along the way. The models are great, but your advantage comes from what you build around it.

[blog] Automate your agent development lifecycle using any coding agent. You can do most anything without leaving your coding harness. Here’s how you build, deploy, govern, evaluate, and share your agent.

Want to get this update sent to you every day? Subscribe to my RSS feed or subscribe via email below:



Read the whole story
alvinashcraft
51 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

v1.0.9-preview.0

1 Share

Feature: agentStop lifecycle hook

Applications can now intercept the natural stopping point of the top-level agent across all SDKs. Return { decision: "block", reason } to enqueue a follow-up message and keep the agent running; omit or return no decision to let it stop normally. (#2054)

session.hooks.agentStop(async ({ stopHookActive }) => {
  if (stopHookActive) return; // don't block continuation turns
  return { decision: "block", reason: "Run final validation and fix any failures." };
});
session.Hooks.AgentStop(async (input, ct) => {
    if (input.StopHookActive) return null; // don't block continuation turns
    return new AgentStopOutput { Decision = "block", Reason = "Run final validation and fix any failures." };
});

Feature: startup timing breakdown for the Rust SDK

Client::start now exposes a StartupTimings struct that breaks down initialization latency into per-phase millisecond fields (process_spawn_ms, transport_setup_ms, handshake_ms, and more), making it easier to diagnose cold-start performance. (#2066)

Feature: [Java] custom JSON schema override for @CopilotToolParam

The @CopilotToolParam annotation now accepts an optional schema attribute for passing an explicit JSON Schema string, enabling support for third-party types that the built-in schema generator cannot automatically map. (#2069)

`@CopilotTool`("Schedule a deployment")
public String scheduleDeployment(
    `@CopilotToolParam`(value = "Deployment time in ISO-8601",
        schema = "{\"type\":\"string\",\"format\":\"date-time\"}")
    com.acme.internal.AcmeDateTime deployTime) { ... }

Other changes

  • improvement: [Java] enforce non-blank @CopilotToolParam descriptions at compile time (#1980)
  • bugfix: [C#] release oversized JSON-RPC receive buffers after large frames to reduce memory retention (#2047)
  • improvement: [Rust] emit type aliases for scalar RPC result schemas in generated code (#2110)

New contributors

  • @adirh3 made their first contribution in #2047

Generated by Release Changelog Generator · sonnet46 45.2 AIC · ⌖ 4.94 AIC · ⊞ 8.6K

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

1.0.76

1 Share

2026-07-29

  • Add enable/disable controls in /plugins for plugins, instructions, agents, LSP servers, and hooks
  • Add support for the grok-4.5 model
  • Sandbox denied paths are enforced for relative and symlinked entries on macOS and Linux (Windows cannot deny per path)
  • Unsent prompt text now stays with the session it was typed for (for the rest of the CLI session) instead of following you to the session you switch to
  • Resuming a session now restores its autopilot or plan mode instead of reverting to interactive, so the autopilot-only task_complete tool stays available and the mode matches the session you left
  • URL permission prompts now keep their sandbox-bypass warning and the model's reason when a host integration rebuilds the prompt, so an elevated fetch is no longer shown as an ordinary one
  • When an update is auto-downloaded, the notification suggests /restart and drops the warning color
  • /diff scrolls and syntax-highlights large multi-file diffs faster
  • Split-view sidebar: hover-to-focus is now off by default (opt in with sidebar.hoverFocus), the active session card is accented by default (opt out with sidebar.accentActiveSession), and the closed-state open sidebar hint always renders in the neutral hint color
  • web_fetch now follows HTTP redirects instead of failing, asking permission for the redirect target when it is on a different origin and showing where the redirect came from
  • Add a directable queue manager (staff) to reorder, edit, remove, repeat, and immediately send queued messages
  • New Sessions sidebar for managing multiple concurrent sessions: switch between them, spawn new ones, and see their status at a glance. Turn it on with experimental mode (/experimental on).
  • Enterprise administrators can enforce a restrictive sandbox floor: managed settings tighten (but never loosen) the user's sandbox policy, and the /sandbox dialog surfaces the org-configured managed values with locked fields and managed filesystem paths so admins can confirm what is enforced.
  • Sessions no longer fail every turn with "Holder terminated during creation" after a subagent finishes
  • Startup tips only suggest /init in repositories that don't already have Copilot instructions
  • A userPromptSubmitted hook returning a non-string value for modifiedPrompt, modifiedTransformedPrompt, or a handled responseContent no longer corrupts the session; the value is ignored, a type-only warning naming the field is logged, an empty-string replacement is rejected instead of blanking the model-facing content, a hook that sets handled without a usable responseContent is now diagnosed instead of silently falling through to the model, and a null additionalContext is treated as absent instead of being injected as the literal text null; hook output is also bounded at 10 MiB per invocation, so an HTTP or command hook returning an unbounded response can no longer exhaust memory or leave an oversized session behind
  • Show recent shell output for large commands that write to a file
  • The /instructions picker now respects --no-custom-instructions.
  • Render inline images in Rio terminals that support Kitty graphics
  • Sandboxed searches now offer an immediate bypass prompt and avoid duplicate bypass prompts.
  • Voice mode pauses playing media before recording and resumes it afterward, where supported (macOS and Windows)
  • Show the number of active scheduled prompts in the footer
  • Add /limits predict to suggest a session AI-credit limit from similar sessions.
  • Add configurable timed refreshes for custom status-line commands
  • Queued messages list no longer shows a blank row or inflated count, and Ctrl+C removes your own newest queued message
  • Changing the mouse setting mid-session now takes effect immediately, from both /settings mouse on|off and the /settings dialog, instead of being saved but ignored until the CLI restarted
  • web_fetch routes through the configured sandbox proxy when outbound is allowed, and denies egress when network.allowOutbound is false (a proxy no longer overrides the user's outbound policy); when a proxied fetch fails it warns that curl/wget share the same proxy, and suggests requestSandboxBypass only when the sandbox proxy itself is unreachable
  • Improve subagent delegation for small tasks and parallel work
  • Queue mid-turn /model changes and apply them after the current response finishes
  • Restore the early warning when unreclaimable system and tool context nears the limit, before automatic compaction is blocked
  • Session working directory no longer reverts to the original checkout shortly after /worktree switches into a new worktree
  • MCP tools load faster from definition-scoped snapshots, with process-wide and per-server cache opt-outs.
  • Autopilot stays selected after task_complete by default; set stayInAutopilot to false to return to interactive mode after each task
Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories