Skip to main content

switchyard_libsy/algorithms/
noop.rs

1// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Test-only algorithm that returns a hard-coded response without calling a backend.
5
6use std::sync::Arc;
7
8use switchyard_protocol::{
9    AggLlmResponse, ContentBlock, LlmResponse, Request, Response, ResponseOutput, Role, StopReason,
10};
11
12use crate::Result;
13use crate::core::algorithm::{Algorithm, Driver};
14use switchyard_protocol::{Context, Decision};
15
16/// Test helper that returns a hard-coded response without routing or model I/O.
17pub struct Noop {}
18
19#[async_trait::async_trait]
20impl Algorithm for Noop {
21    fn name(&self) -> &str {
22        "noop"
23    }
24
25    async fn create_run_task(
26        self: Arc<Self>,
27        ctx: Context,
28        driver: Driver,
29        request: Request,
30    ) -> Result<Response> {
31        let model = request
32            .requested_model()
33            .unwrap_or("switchyard/noop")
34            .to_string();
35        let decision: Arc<Decision> = Arc::new(Decision::new(
36            model.clone(),
37            Some("noop returned its synthetic response".to_string()),
38            true,
39        ));
40        driver.info(ctx, decision.clone()).await?;
41
42        let llm_response = LlmResponse::Agg(AggLlmResponse {
43            id: Some("switchyard-noop".to_string()),
44            model: Some(model),
45            outputs: vec![ResponseOutput {
46                role: Role::Assistant,
47                content: vec![ContentBlock::Text {
48                    text: "OK".to_string(),
49                }],
50                stop_reason: Some(StopReason::EndTurn),
51            }],
52            ..Default::default()
53        });
54        let response = Response {
55            llm_response,
56            metadata: request.metadata.clone(),
57        };
58        Ok(response)
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use switchyard_protocol::{LlmRequest, Message, Role};
65
66    use super::*;
67    use crate::core::testing::{echo, test_drive};
68
69    #[tokio::test]
70    async fn test_noop_algo() -> Result<()> {
71        const TEST_MODEL: &str = "test_noop_algo";
72        let request = Request {
73            llm_request: LlmRequest {
74                model: Some(TEST_MODEL.to_string()),
75                messages: vec![Message::text(Role::User, "hi")],
76                ..LlmRequest::default()
77            },
78            raw_request: None,
79            metadata: None,
80        };
81
82        // `Noop` synthesizes its own response and never offloads a call, so `echo` is
83        // never reached.
84        let a: Arc<dyn Algorithm> = Arc::new(Noop {});
85        let (decisions, response) = test_drive(a, Context::default(), request, echo()).await?;
86        let Some(decision) = decisions.first() else {
87            panic!("Expected exactly one Decision");
88        };
89        assert_eq!(decision.selected_model_id(), TEST_MODEL);
90        assert!(decision.is_answer_call());
91        assert_eq!(response.selected_model(), Some(TEST_MODEL));
92        Ok(())
93    }
94}