#14395: feat: add gateway.nodes.execEvents config to control exec completion system messages
gateway
stale
size: XS
Cluster:
Tool Execution and Error Handling
## Summary
Adds a new config option `gateway.nodes.execEvents` to control how async exec completion events are surfaced in chat sessions.
### The Problem
When using the `nodes` tool to run commands on remote nodes, completion results are delivered **twice**:
1. As the tool call response (used by the agent immediately)
2. As a `System: Exec finished...` system event injected into the chat session
This causes duplicate context consumption — the same output (docker listings, file contents, etc.) appears multiple times in the conversation history, wasting tokens and degrading effective context window size.
### Solution
New config option `gateway.nodes.execEvents` with three modes:
| Mode | Behavior |
|------|----------|
| `inject` (default) | Current behavior — full output injected as system messages |
| `notify` | Brief one-liner notification without output body |
| `silent` | Suppressed entirely (heartbeat still fires) |
### Config Example
```json
{
"gateway": {
"nodes": {
"execEvents": "silent"
}
}
}
```
### Changes
- `src/config/types.gateway.ts` — Added `execEvents` to `GatewayNodesConfig` type
- `src/config/zod-schema.ts` — Added Zod validation for the new field
- `src/config/schema.hints.ts` — Added UI label
- `src/config/schema.field-metadata.ts` — Added label + description
- `src/gateway/server-node-events.ts` — Reads config and gates system event injection
### Backward Compatible
Default is `inject` which preserves existing behavior. No breaking changes.
Closes #4074
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR adds a new `gateway.nodes.execEvents` configuration option (schema + UI metadata) to control whether async node exec events are injected into chat sessions as system messages.
Key changes:
- Extends `GatewayNodesConfig` and config validation (`src/config/types.gateway.ts`, `src/config/zod-schema.ts`).
- Adds UI labels/help text (`src/config/schema.hints.ts`, `src/config/schema.field-metadata.ts`).
- Updates node event handling to conditionally enqueue system events for `exec.*` events based on the new config (`src/gateway/server-node-events.ts`).
<h3>Confidence Score: 4/5</h3>
- Mostly safe to merge, but clarify/fix execEvents scoping and consider avoiding per-event config loads.
- The config/type/schema updates are consistent and low risk, but the event gating currently applies to exec.started/exec.denied as well as completion, which may be an unintended behavioral change relative to the stated goal. Also, calling loadConfig() on every exec event can create unnecessary overhead when the config cache expires.
- src/gateway/server-node-events.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#22835: feat: add tools.nodes.notifyOnExit config flag
by abbudjoe · 2026-02-21
84.2%
#20209: fix(node): respect tools.exec.notifyOnExit for node exec events
by zerone0x · 2026-02-18
76.0%
#3396: Config: gateway.unhandledRejections (warn|exit)
by diegoaledesma · 2026-01-28
75.7%
#20394: feat(gateway): make chat history byte limit configurable via gatewa...
by mgratch · 2026-02-18
73.1%
#8713: feat: gateway memory monitor, install linger, docs and failover
by quratus · 2026-02-04
72.6%
#9218: Fix Control UI chat resync on gaps and terminal events
by figitaki · 2026-02-05
72.5%
#11300: feat(exec): make shell configurable via tools.exec.shell
by imjszhang · 2026-02-07
72.4%
#5823: fix(config): exit cleanly on invalid config instead of high CPU loop
by gavinbmoore · 2026-02-01
72.4%
#14127: fix(exec): return command output when gateway approval is Always Allow
by Siziff · 2026-02-11
72.3%
#14811: feat(gateway): route chat/agent events per-connection instead of glob…
by jiangjin11 · 2026-02-12
72.1%