Skip to main content

claude_api/messages/
thinking.rs

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