feat: add hide_agent_reasoning config option (#1181)

This PR introduces a `hide_agent_reasoning` config option (that defaults
to `false`) that users can enable to make the output less verbose by
suppressing reasoning output.

To test, verified that this includes agent reasoning in the output:

```
echo hello | just exec
```

whereas this does not:

```
echo hello | just exec --config hide_agent_reasoning=false
```
This commit is contained in:
Michael Bolin
2025-05-30 23:14:56 -07:00
committed by GitHub
parent 4f3d294762
commit e81327e5f4
5 changed files with 45 additions and 11 deletions

View File

@@ -354,6 +354,16 @@ Note this is **not** a general editor setting (like `$EDITOR`), as it only accep
Currently, `"vscode"` is the default, though Codex does not verify VS Code is installed. As such, `file_opener` may default to `"none"` or something else in the future.
## hide_agent_reasoning
Codex intermittently emits "reasoning" events that show the models internal "thinking" before it produces a final answer. Some users may find these events distracting, especially in CI logs or minimal terminal output.
Setting `hide_agent_reasoning` to `true` suppresses these events in **both** the TUI as well as the headless `exec` sub-command:
```toml
hide_agent_reasoning = true # defaults to false
```
## project_doc_max_bytes
Maximum number of bytes to read from an `AGENTS.md` file to include in the instructions sent with the first turn of a session. Defaults to 32 KiB.

View File

@@ -42,6 +42,11 @@ pub struct Config {
pub shell_environment_policy: ShellEnvironmentPolicy,
/// When `true`, `AgentReasoning` events emitted by the backend will be
/// suppressed from the frontend output. This can reduce visual noise when
/// users are only interested in the final agent responses.
pub hide_agent_reasoning: bool,
/// Disable server-side response storage (sends the full conversation
/// context with every request). Currently necessary for OpenAI customers
/// who have opted into Zero Data Retention (ZDR).
@@ -272,6 +277,10 @@ pub struct ConfigToml {
/// Collection of settings that are specific to the TUI.
pub tui: Option<Tui>,
/// When set to `true`, `AgentReasoning` events will be hidden from the
/// UI/output. Defaults to `false`.
pub hide_agent_reasoning: Option<bool>,
}
fn deserialize_sandbox_permissions<'de, D>(
@@ -433,6 +442,8 @@ impl Config {
file_opener: cfg.file_opener.unwrap_or(UriBasedFileOpener::VsCode),
tui: cfg.tui.unwrap_or_default(),
codex_linux_sandbox_exe,
hide_agent_reasoning: cfg.hide_agent_reasoning.unwrap_or(false),
};
Ok(config)
}
@@ -774,6 +785,7 @@ disable_response_storage = true
file_opener: UriBasedFileOpener::VsCode,
tui: Tui::default(),
codex_linux_sandbox_exe: None,
hide_agent_reasoning: false,
},
o3_profile_config
);
@@ -813,6 +825,7 @@ disable_response_storage = true
file_opener: UriBasedFileOpener::VsCode,
tui: Tui::default(),
codex_linux_sandbox_exe: None,
hide_agent_reasoning: false,
};
assert_eq!(expected_gpt3_profile_config, gpt3_profile_config);
@@ -867,6 +880,7 @@ disable_response_storage = true
file_opener: UriBasedFileOpener::VsCode,
tui: Tui::default(),
codex_linux_sandbox_exe: None,
hide_agent_reasoning: false,
};
assert_eq!(expected_zdr_profile_config, zdr_profile_config);

View File

@@ -43,10 +43,13 @@ pub(crate) struct EventProcessor {
red: Style,
green: Style,
cyan: Style,
/// Whether to include `AgentReasoning` events in the output.
show_agent_reasoning: bool,
}
impl EventProcessor {
pub(crate) fn create_with_ansi(with_ansi: bool) -> Self {
pub(crate) fn create_with_ansi(with_ansi: bool, show_agent_reasoning: bool) -> Self {
let call_id_to_command = HashMap::new();
let call_id_to_patch = HashMap::new();
let call_id_to_tool_call = HashMap::new();
@@ -63,6 +66,7 @@ impl EventProcessor {
green: Style::new().green(),
cyan: Style::new().cyan(),
call_id_to_tool_call,
show_agent_reasoning,
}
} else {
Self {
@@ -76,6 +80,7 @@ impl EventProcessor {
green: Style::new(),
cyan: Style::new(),
call_id_to_tool_call,
show_agent_reasoning,
}
}
}
@@ -411,12 +416,14 @@ impl EventProcessor {
// Should we exit?
}
EventMsg::AgentReasoning(agent_reasoning_event) => {
ts_println!(
self,
"{}\n{}",
"thinking".style(self.italic).style(self.magenta),
agent_reasoning_event.text
);
if self.show_agent_reasoning {
ts_println!(
self,
"{}\n{}",
"thinking".style(self.italic).style(self.magenta),
agent_reasoning_event.text
);
}
}
EventMsg::SessionConfigured(session_configured_event) => {
let SessionConfiguredEvent {

View File

@@ -112,7 +112,8 @@ pub async fn run_main(cli: Cli, codex_linux_sandbox_exe: Option<PathBuf>) -> any
};
let config = Config::load_with_cli_overrides(cli_kv_overrides, overrides)?;
let mut event_processor = EventProcessor::create_with_ansi(stdout_with_ansi);
let mut event_processor =
EventProcessor::create_with_ansi(stdout_with_ansi, !config.hide_agent_reasoning);
// Print the effective configuration and prompt so users can see what Codex
// is using.
event_processor.print_config_summary(&config, &prompt);

View File

@@ -239,9 +239,11 @@ impl ChatWidget<'_> {
self.request_redraw();
}
EventMsg::AgentReasoning(AgentReasoningEvent { text }) => {
self.conversation_history
.add_agent_reasoning(&self.config, text);
self.request_redraw();
if !self.config.hide_agent_reasoning {
self.conversation_history
.add_agent_reasoning(&self.config, text);
self.request_redraw();
}
}
EventMsg::TaskStarted => {
self.bottom_pane.set_task_running(true);