Skip to main content

claude_api/messages/
thinking.rs

1//! Configuration for extended thinking.
2//!
3//! Pass a [`ThinkingConfig::Enabled`] value in the request to have the model
4//! emit `thinking` blocks before its final answer. `budget_tokens` caps how
5//! much of `max_tokens` the model may spend on reasoning.
6//!
7//! Extended thinking is supported by Claude Sonnet 4.6+ and Claude Opus 4.x.
8//! See [`crate::models::ModelCapabilities`] to check model support at runtime.
9
10use serde::{Deserialize, Serialize};
11
12/// Whether and how the model should produce extended-thinking output.
13///
14/// When [`ThinkingConfig::Enabled`], the model emits one or more
15/// [`Thinking`](crate::messages::content::KnownBlock::Thinking) blocks
16/// before its final answer. `budget_tokens` caps the thinking length;
17/// it counts against `max_tokens`.
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
19#[serde(tag = "type", rename_all = "snake_case")]
20#[non_exhaustive]
21pub enum ThinkingConfig {
22    /// Enable extended thinking with a per-turn token budget.
23    Enabled {
24        /// Maximum tokens the model may spend thinking on this turn.
25        budget_tokens: u32,
26    },
27    /// Disable extended thinking explicitly.
28    Disabled,
29}
30
31impl ThinkingConfig {
32    /// Convenience constructor for the [`ThinkingConfig::Enabled`] variant.
33    #[must_use]
34    pub fn enabled(budget_tokens: u32) -> Self {
35        Self::Enabled { budget_tokens }
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42    use pretty_assertions::assert_eq;
43    use serde_json::json;
44
45    #[test]
46    fn enabled_round_trips() {
47        let c = ThinkingConfig::enabled(8192);
48        let v = serde_json::to_value(c).unwrap();
49        assert_eq!(v, json!({"type": "enabled", "budget_tokens": 8192}));
50        let parsed: ThinkingConfig = serde_json::from_value(v).unwrap();
51        assert_eq!(parsed, c);
52    }
53
54    #[test]
55    fn disabled_round_trips() {
56        let c = ThinkingConfig::Disabled;
57        let v = serde_json::to_value(c).unwrap();
58        assert_eq!(v, json!({"type": "disabled"}));
59        let parsed: ThinkingConfig = serde_json::from_value(v).unwrap();
60        assert_eq!(parsed, c);
61    }
62}