Skip to main content

switchyard_libsy/algorithms/
passthrough.rs

1// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Single-target routing for direct model calls and integration diagnostics.
5
6use std::sync::Arc;
7
8use switchyard_protocol::{Request, Response};
9
10use crate::Result;
11use crate::core::algorithm::{Algorithm, Driver, LlmTarget, RoutedRequest};
12use switchyard_protocol::{Context, Decision};
13
14/// Routing algorithm that always calls one configured target.
15pub struct Passthrough {
16    target: LlmTarget,
17}
18
19impl Passthrough {
20    /// Creates an algorithm that always calls `target`.
21    pub fn new(target: LlmTarget) -> Self {
22        Passthrough { target }
23    }
24}
25
26#[async_trait::async_trait]
27impl Algorithm for Passthrough {
28    fn name(&self) -> &str {
29        "passthrough"
30    }
31
32    async fn create_run_task(
33        self: Arc<Self>,
34        ctx: Context,
35        driver: Driver,
36        request: Request,
37    ) -> Result<Response> {
38        let decision: Arc<Decision> = Arc::new(Decision::new(
39            self.target.semantic_name.clone(),
40            Some(format!(
41                "passthrough selected target '{}'",
42                self.target.semantic_name
43            )),
44            true,
45        ));
46        driver.info(ctx.clone(), decision.clone()).await?;
47        driver
48            .call_llm(RoutedRequest {
49                request,
50                decision,
51                ctx,
52            })
53            .await
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use std::sync::Arc;
60
61    use super::Passthrough;
62    use crate::core::algorithm::{Algorithm, LlmTarget};
63    use crate::core::testing::{echo, test_drive};
64    use switchyard_protocol::{Context, Request, completion_text, text_request};
65
66    #[tokio::test]
67    async fn test_passthrough() -> crate::Result<()> {
68        const MODEL_ID: &str = "testing/passthrough";
69        let request = Request {
70            llm_request: text_request(Some("auto".to_string()), "hi"),
71            raw_request: None,
72            metadata: None,
73        };
74        let algorithm: Arc<dyn Algorithm> = Arc::new(Passthrough::new(LlmTarget {
75            semantic_name: MODEL_ID.to_string(),
76        }));
77        let (trace, response) = test_drive(algorithm, Context::default(), request, echo()).await?;
78
79        assert_eq!(
80            response
81                .llm_response
82                .as_agg()
83                .map(completion_text)
84                .unwrap_or_default(),
85            MODEL_ID
86        );
87        assert_eq!(trace.len(), 1);
88        assert_eq!(trace[0].selected_model_id(), MODEL_ID);
89        assert!(trace[0].is_answer_call());
90        Ok(())
91    }
92}