Latest Rust SDK #97
Conversation
- Introduced RunAgentClientConfig struct for improved configuration management. - Updated client initialization to support builder pattern for optional parameters. - Enhanced documentation with examples for creating clients using both direct construction and builder pattern. - Improved error handling and logging for local agent configuration. - Added support for enabling/disabling database registry lookup in client configuration.
WalkthroughThis PR introduces a configuration-driven architecture for the Rust SDK, replacing direct constructor parameters with a Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Config as RunAgentClientConfig
participant AsyncClient as RunAgentClient (Async)
participant BlockingClient as RunAgentClient (Blocking)
participant Runtime as Tokio Runtime
participant RestClient
participant SocketClient
User->>Config: Build with RunAgentClientConfig { agent_id, entrypoint_tag, ... }
rect rgb(200, 230, 255)
Note over User,SocketClient: Async Path
User->>AsyncClient: RunAgentClient::new(config).await
AsyncClient->>RestClient: initialize_architecture()
RestClient-->>AsyncClient: AgentArchitecture
AsyncClient->>User: Ready
User->>AsyncClient: run(¶ms).await
AsyncClient->>SocketClient: Send message
SocketClient->>SocketClient: deserialize_object() with prepare_for_deserialization()
SocketClient-->>AsyncClient: Value
AsyncClient-->>User: RunAgentResult<Value>
end
rect rgb(200, 255, 230)
Note over User,Runtime: Blocking Path (New)
User->>BlockingClient: RunAgentClient::new(config)?
BlockingClient->>Runtime: Spawn embedded runtime
BlockingClient->>AsyncClient: Initialize async client
BlockingClient->>User: Ready
User->>BlockingClient: run(¶ms)?
BlockingClient->>Runtime: Block on async call
Runtime->>AsyncClient: run().await
AsyncClient-->>Runtime: Result
Runtime-->>BlockingClient: Extract result
BlockingClient-->>User: RunAgentResult<Value>
end
rect rgb(255, 240, 200)
Note over AsyncClient: Error Handling (Enhanced)
AsyncClient->>AsyncClient: Parse response envelope
alt success: true
AsyncClient->>AsyncClient: Extract & deserialize data
else success: false
AsyncClient->>AsyncClient: Create RunAgentError::Execution { code, message, suggestion }
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (6)
test_scripts/rust/test_agno/Cargo.toml (1)
6-14: Avoid absolute, user-specific path for the runagent dependencyThe
runagentdependency now points to an absolute path under/home/azureuser/..., which will not resolve on other machines or CI environments:runagent = { path = "/home/azureuser/runagent/runagent-rust/runagent" }For shared test scripts, prefer either:
- A relative path within the repo (e.g.,
path = "../../../runagent-rust/runagent"), or- A versioned crates.io dependency once the new SDK is published.
Also, the comment “from crates.io” is now misleading and should be updated or removed.
test_scripts/rust/test_parlant/src/main.rs (1)
1-36: Critical: Duplicatemainfunction will cause compilation error.This file defines a
mainfunction, but there's anothermainfunction at Line 47. Rust programs can only have one entry point. Additionally, imports are duplicated at Line 1 and Line 42.To fix this issue, either:
- Keep only one
mainfunction and combine the tests- Convert one example to a separate binary or test case
- Comment out one of the
mainfunctions (though this is not ideal)Recommended approach - combine into one main:
use runagent::{RunAgentClient, RunAgentClientConfig}; use serde_json::json; use futures::StreamExt; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { println!("🧪 Testing Parlant Agent with Rust SDK"); println!("======================================="); let agent_id = "9c39620c-c309-4478-a44e-2a45e254a9fb"; - // ============================================ - // NON-STREAMING TESTS - // ============================================ - - // Test 1: Simple Chat + // Test 1: Non-Streaming Simple Chat println!("\n1️⃣ Testing Simple Chat"); let simple_client = RunAgentClient::new(RunAgentClientConfig { agent_id: agent_id.to_string(), entrypoint_tag: "parlant_simple".to_string(), local: Some(true), ..RunAgentClientConfig::default() }).await?; let simple_response = simple_client.run(&[ ("message", json!("What's the weather like in Paris?")) ]).await?; println!("✅ Simple Chat Response:"); println!("{}", serde_json::to_string_pretty(&simple_response)?); + // Test 2: Streaming Chat + println!("\n2️⃣ Testing Streaming Chat"); + println!("{}", "-".repeat(30)); + + let stream_client = RunAgentClient::new(RunAgentClientConfig { + agent_id: agent_id.to_string(), + entrypoint_tag: "parlant_stream".to_string(), + local: Some(true), + ..RunAgentClientConfig::default() + }).await?; + + let mut stream = stream_client.run_stream(&[ + ("message", json!("can you tell me the sum of 10 to 20.")) + ]).await?; + + println!("✅ Streaming Response:"); + while let Some(chunk_result) = stream.next().await { + match chunk_result { + Ok(chunk) => { + print!("{}", chunk); + }, + Err(e) => { + println!("❌ Stream Error: {}", e); + break; + } + } + } Ok(()) } - - - -// ############################streaming################################## - -use runagent::{RunAgentClient, RunAgentClientConfig}; -use serde_json::json; -use futures::StreamExt; - -#[tokio::main] -async fn main() -> Result<(), Box<dyn std::error::Error>> { - println!("🧪 Testing Parlant Agent with Rust SDK"); - println!("======================================="); - - // Replace with the actual agent ID from `runagent serve` - let agent_id = "9c39620c-c309-4478-a44e-2a45e254a9fb"; - - // Test 5: Streaming Chat - println!("\n5️⃣ Testing Streaming Chat"); - println!("{}", "-".repeat(30)); - - let stream_client = RunAgentClient::new(RunAgentClientConfig { - agent_id: agent_id.to_string(), - entrypoint_tag: "parlant_stream".to_string(), - local: Some(true), - ..RunAgentClientConfig::default() - }).await?; - - let mut stream = stream_client.run_stream(&[ - ("message", json!("can you tell me the sum of 10 to 20.")) - ]).await?; - - println!("✅ Streaming Response:"); - while let Some(chunk_result) = stream.next().await { - match chunk_result { - Ok(chunk) => { - print!("{}", chunk); - }, - Err(e) => { - println!("❌ Stream Error: {}", e); - break; - } - } - } - - Ok(()) -}test_scripts/rust/test_crewai/src/main.rs (1)
4-6: Multiplemainfunctions will cause compilation failure—consolidate or split into separate binary targetsThe file contains two
#[tokio::main] async fn main()functions (lines 4–5 and 40–41), which creates a duplicate entry point error in a single binary crate. Additionally, both main functions configureRunAgentClientwithlocal: Some(true)and no explicithost/port, creating an undocumented dependency on registry/DB lookup for agent resolution.Options to resolve:
- Remove or comment out one main function to keep a single entry point
- Split into separate binary targets (one for non-streaming, one for streaming tests)
- Add conditional compilation (
#[cfg(...)]) to gate one of the functions- If keeping both, clarify the registry requirement in documentation or add explicit
host/portconfigurationtest_scripts/rust/test_autogen/src/main.rs (1)
4-6: Remove onemainfunction or split into separate binaries; addhost/portto client configs or document registry requirement.The file contains two
#[tokio::main] async fn main()functions (lines 5 and 46) withoutcfggating or binary separation inCargo.toml. This will cause a duplicatemaincompilation error.Both client configurations use
local: Some(true)but omithostandport(lines 16–21 and 55–60), which requires the agent to be registered in the registry/database for resolution. Either:
- Add
hostandportvalues matching your running AutoGen agent- Or document that the
dbfeature must be enabled and the agent must be pre-registeredtest_scripts/rust/test_ag2/src/main.rs (1)
4-6: Fix compilation error: two#[tokio::main]functions in single binary crateThe file defines two
#[tokio::main] async fn main()functions (lines 4 and 47), which will fail to compile in a single binary crate. Rust allows only onemainentry point.Options to fix:
- Split into separate binaries with
[[bin]]sections in Cargo.toml- Gate one with
#[cfg(...)]conditional compilation- Merge both into a single
mainfunctionAdditionally, both
RunAgentClientConfiginstances setlocal: Some(true)(lines 19 and 55) without explicitly providinghost/port. Verify this matches your expected runtime configuration, particularly if the registry/DB lookup path may be unavailable or if you intend to connect to a specific localhost address.runagent-rust/runagent/src/client/runagent_client.rs (1)
297-338: Architecture initialization validates entrypoint but doesn’t handle missingentrypointskey
initialize_architecturestores the fetched architecture and callsvalidate_entrypoint, which:
- Scans
architecture["entrypoints"]for the configured tag.- Logs available tags and returns a validation error when the tag isn’t found.
However, when
entrypointsis missing or not an array,validate_entrypointsilently returnsOk(()). The README suggestsARCHITECTURE_MISSINGshould be raised whendata.entrypointsis missing.To align behavior with the docs and make misconfigured agents easier to debug, consider adding an explicit check:
- If
entrypointsis absent or not an array, return an appropriateRunAgentError(e.g.,ExecutionwithARCHITECTURE_MISSINGorconfig/validation) rather than silently succeeding.
🧹 Nitpick comments (17)
templates/agno/default/simple_assistant.py (1)
20-31: Update the comment to reflect all checked attributes.The comment on line 21 mentions
.contentand.messagesattributes but doesn't mention.text, which is also checked on line 27. Consider updating the comment to accurately reflect all fallback paths.The defensive cascading approach with multiple fallbacks is appropriate for a template, as it handles various response object formats robustly.
Apply this diff to update the comment:
- # Extract the actual content from the response object - # The response object has a .content attribute or .messages attribute + # Extract the actual content from the response object + # Try in order: .content, .messages[-1].content, .text, or string fallback if hasattr(response, 'content'):sdk_checklist.md (1)
150-150: Move repository hygiene requirements into the Implementation Checklist.Lines 150 introduces new repository hygiene requirements (README, PUBLISH.md) that logically belong in the "Implementation Checklist (Per New SDK)" section (line 125). This co-locates all per-SDK deliverables in one place and makes it easier for contributors to verify completeness.
runagent-rust/PUBLISH.md (1)
1-49: Rust SDK publishing checklist is clear and actionableThe release steps (version bump, fmt/clippy/test,
cargo package, thencargo publishplus tagging) form a solid, reproducible workflow for publishingrunagent. This should make future releases much less error‑prone.If you care about copy style, you could vary the phrasing of the three “Update ...” bullets in the Version Bump section, but that’s purely cosmetic.
examples/lead-agent/backend-rust/src/main.rs (2)
11-15: Importing RunAgentClientConfig and updating RUNAGENT_ID is fine; consider configurabilityBringing in
RunAgentClientConfigmatches the new SDK API, and the updatedRUNAGENT_IDis straightforward. For a production deployment, you might eventually want to source the agent ID from configuration or environment rather than a hard‑coded constant, but this is acceptable for an example backend.
150-192: run() usage and payload unwrapping logic are robustSwitching to
client.run(¶ms).awaitaligns with the updated SDK, and the follow‑up logic to:
- log the raw result,
- extract a
"payload"field when present, and- fall back to parsing stringified JSON,
is defensive without risking panics—parse failures just return the original
result. This should handle both structured and string‑wrapped responses gracefully.runagent-rust/runagent/src/types/errors.rs (2)
3-49: Execution error variant and constructor look solid; consider loosening the generic constraintThe new
Executionvariant with structuredcode,message,suggestion, anddetails: Option<Value>is a good extension point and the display format is clear. Theexecutionconstructor is fine, but using a singleS: Into<String>for bothcodeandmessageforces them to be the same type; it can be more ergonomic to allow different types (e.g.,&'static strfor code andStringfor message).You could simplify call‑sites by changing the signature to something like separate generics or
impl Into<String>per parameter so callers can freely mix&strandString.Also applies to: 125-138
147-172: Retryability semantics forExecutionerrors are clear and narrowly scopedExtending
category()with"execution"and treating onlyExecutionerrors with codes"CONNECTION_ERROR"or"SERVER_ERROR"as retryable keeps the behavior predictable and backward compatible with existing variants. This is a reasonable design, especially if these codes map to server-defined semantics.It might be worth adding unit tests specifically for
Execution(category,Display, andis_retryable) to prevent regressions as new codes are introduced.runagent-rust/runagent/src/utils/config.rs (2)
39-59: Env-based load and base_url normalization are reasonable; be explicit about expected input shapeLoading
api_keyandbase_urlfromENV_RUNAGENT_API_KEY/ENV_RUNAGENT_BASE_URLand auto‑prefixing non‑http(s)URLs withhttps://is a sensible default and should reduce misconfigurations. One thing to consider is documenting (in crate docs or README) that bare hosts likeapi.example.comwill be treated ashttps://api.example.com, so users aren’t surprised by implicit TLS.The comment about “stored in SQLite” is forward-looking; if configuration isn’t actually persisted to SQLite yet, clarifying that this function only reads from env (and that DB integration lives elsewhere) would avoid confusion.
62-97:setupbehavior is clear but_savebeing ignored and auth being a stub should be documentedThe updated
setuppath—merging env‑derived config with optionalapi_key/base_url, enforcing presence of an API key, and normalizing the base URL—looks fine. However:
_saveis intentionally ignored; callers expecting persistence may be surprised.test_authenticationis currently a stub that returnsOk(true)whenever an API key is set, so theAuthenticationerror branch is effectively unreachable for now.Explicitly documenting in the public API (doc comments or higher-level docs) that
setupdoes not persist to disk and that authentication checks are placeholders will set more accurate expectations until the SQLite-backed implementation is wired in.runagent-rust/runagent/examples/test_deserialize.rs (1)
4-17: Consider using?operator for consistency with other examples.While
unwrap()is acceptable in example code, using the?operator would be more consistent with the error handling patterns shown in other examples and demonstrate best practices.-fn main() { - let serializer = CoreSerializer::new(10.0).unwrap(); +fn main() -> Result<(), Box<dyn std::error::Error>> { + let serializer = CoreSerializer::new(10.0)?; // Test the exact structure we're getting let test_response = json!({ "payload": "\"Hello, world!\"", "type": "string" }); println!("Input: {}", test_response); - let result = serializer.deserialize_object(test_response).unwrap(); + let result = serializer.deserialize_object(test_response)?; println!("Result: {}", result); println!("Result is string: {}", result.is_string()); + Ok(()) }test_scripts/rust/test_agno/src/main.rs (1)
1-62: Consider: Cleanup commented-out code.The file contains extensive commented-out examples showing different usage patterns (sync/async, streaming/non-streaming). While these may serve as reference, consider:
- Moving them to separate example files
- Adding them to documentation
- Removing if no longer needed
This would improve maintainability.
runagent-rust/runagent/src/utils/serializer.rs (1)
59-99: Clarify string payload handling and add targeted testsThe extended
deserialize_objectlogic for{type, payload}and string responses is reasonable, but a couple of points are worth tightening up:
- For
{type, payload}wherepayloadis a JSON string, you return the parsedValuedirectly rather than feeding it throughreconstruct_nested_json. If those payloads can themselves be serialized{strategy, content}wrappers, you may want to run the parsed value throughreconstruct_nested_jsonto keep behavior consistent with the non-string payload path.- There are no tests covering:
{type, payload}with string vs non-string payload,- top-level string JSON (both valid JSON and non-JSON),
- legacy
{content}structures when wrapped inside{type, payload}.Consider adding small unit tests for these shapes and, if needed, routing the parsed string payload through
reconstruct_nested_jsonfor full symmetry with other paths.runagent-rust/runagent/src/lib.rs (1)
258-279: Blocking module docs vs exports: confirmRunAgentClientConfigre-exportThe new blocking wrapper and exports look good overall (
pub mod blocking;pluspub use blocking::{RunAgentClient as BlockingRunAgentClient, BlockingStream};), but the example in the blocking docs uses:use runagent::blocking::{RunAgentClient, RunAgentClientConfig};For that to compile, the
blockingmodule needs to publicly re-exportRunAgentClientConfig(e.g.,pub use crate::client::RunAgentClientConfig;). IfRunAgentClientConfigis only exported from the crate root, it would be clearer either to:
- Re-export
RunAgentClientConfigfromrunagent::blocking, or- Change the example to
use runagent::{BlockingRunAgentClient as RunAgentClient, RunAgentClientConfig};.Worth confirming the actual exports in
blocking.rsand aligning the example with them.Also applies to: 282-287
runagent-rust/runagent/src/constants.rs (1)
1-22: Align timeout constant and reuse API prefix where possible
DEFAULT_TIMEOUT_SECONDSis documented as the default execution timeout (5 minutes, value 300), but the HTTP client and WebSocket stream both hardcode 600 seconds. This mismatch can confuse users and future maintainers.Consider either:
- Updating
DEFAULT_TIMEOUT_SECONDSto 600 and using it inRestClient/WebSocket payloads, or- Adjusting the docs/name to match current behavior.
Similarly,
DEFAULT_API_PREFIXcould be used instead of repeated"/api/v1"literals in client constructors to keep things in sync.runagent-rust/runagent/README.md (1)
278-287: Double‑check that documented troubleshooting codes are actually emittedThe troubleshooting table relies on specific codes (
STREAM_ENTRYPOINT,NON_STREAM_ENTRYPOINT,AGENT_NOT_FOUND_LOCAL/REMOTE,AUTHENTICATION_ERROR,ARCHITECTURE_MISSING). Some of these depend on server responses or helper mapping in lower-level clients.It would be good to confirm that every code listed here is actually produced by the current Rust client + backend paths; otherwise, consider pruning or annotating entries that are not yet wired up to avoid confusing users.
runagent-rust/runagent/src/client/runagent_client.rs (2)
31-115: Config struct is well‑designed; consider implementingDefaulttrait
RunAgentClientConfigcleanly centralizes all construction options and the builder methods (with_local,with_address,with_api_key, etc.) make typical flows ergonomic.You currently provide a
pub fn default() -> Selfassociated function mainly to support..RunAgentClientConfig::default()in examples. Implementing the standardDefaulttrait instead (and keeping adefault()inherent method only if you really need it) would integrate better with Rust conventions and tooling, while preserving the same usage pattern viaRunAgentClientConfig::default().Not urgent, but worth considering as this type is now the primary entry point for the SDK.
543-563: Remote client creation: reuse constants and clarify scheme fallback
create_remote_clientsdoes the right thing in general:
- Uses
RestClient::new(base_url, api_key, Some("/api/v1")).- Derives the WebSocket base URL from the HTTP base (
https://→wss://,http://→ws://, elsewss://{base_url}).- Falls back to
RestClient::default()/SocketClient::default()when no override is provided.Two minor improvements:
- Reuse
DEFAULT_API_PREFIXhere instead of the"/api/v1"literal to keep everything in sync withconstants.rs.- Consider whether the default of
wss://{base_url}for scheme‑less URLs is what you want (vs.ws://). If this is intentional, maybe add a short doc comment stating that scheme‑less base URLs are treated as secure by default.These are small but make the behavior more explicit and maintainable.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (38)
examples/lead-agent/backend-rust/src/main.rs(5 hunks)examples/lead-agent/lead-score-flow/runagent.config.json(1 hunks)runagent-rust/PUBLISH.md(1 hunks)runagent-rust/examples/async_example.rs(1 hunks)runagent-rust/examples/direct_construction.rs(1 hunks)runagent-rust/examples/sync_example.rs(1 hunks)runagent-rust/runagent/Cargo.toml(1 hunks)runagent-rust/runagent/README.md(1 hunks)runagent-rust/runagent/examples/async_example.rs(1 hunks)runagent-rust/runagent/examples/direct_construction.rs(1 hunks)runagent-rust/runagent/examples/direct_construction_omitted.rs(1 hunks)runagent-rust/runagent/examples/sync_example.rs(1 hunks)runagent-rust/runagent/examples/test_deserialize.rs(1 hunks)runagent-rust/runagent/src/blocking.rs(1 hunks)runagent-rust/runagent/src/client/mod.rs(1 hunks)runagent-rust/runagent/src/client/rest_client.rs(1 hunks)runagent-rust/runagent/src/client/runagent_client.rs(5 hunks)runagent-rust/runagent/src/client/socket_client.rs(2 hunks)runagent-rust/runagent/src/constants.rs(1 hunks)runagent-rust/runagent/src/db/service.rs(1 hunks)runagent-rust/runagent/src/lib.rs(8 hunks)runagent-rust/runagent/src/types/errors.rs(5 hunks)runagent-rust/runagent/src/types/schema.rs(2 hunks)runagent-rust/runagent/src/utils/config.rs(4 hunks)runagent-rust/runagent/src/utils/serializer.rs(1 hunks)sdk_checklist.md(2 hunks)templates/agno/default/runagent.config.json(2 hunks)templates/agno/default/simple_assistant.py(1 hunks)test_scripts/python/client_test_agno.py(1 hunks)test_scripts/rust/test_ag2/src/main.rs(4 hunks)test_scripts/rust/test_agno/Cargo.toml(1 hunks)test_scripts/rust/test_agno/src/main.rs(1 hunks)test_scripts/rust/test_autogen/src/main.rs(4 hunks)test_scripts/rust/test_crewai/src/main.rs(4 hunks)test_scripts/rust/test_langchain/src/main.rs(2 hunks)test_scripts/rust/test_langgraph/src/main.rs(2 hunks)test_scripts/rust/test_letta/src/main.rs(2 hunks)test_scripts/rust/test_parlant/src/main.rs(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (23)
runagent-rust/runagent/src/client/socket_client.rs (2)
runagent-rust/runagent/src/utils/serializer.rs (2)
prepare_for_deserialization(38-48)deserialize_object(58-100)runagent-rust/runagent/src/types/errors.rs (1)
server(91-95)
runagent-rust/examples/direct_construction.rs (1)
runagent-rust/runagent/src/client/runagent_client.rs (2)
new(97-109)new(194-295)
runagent-rust/runagent/examples/sync_example.rs (3)
runagent-rust/examples/async_example.rs (1)
main(9-26)runagent-rust/runagent/src/blocking.rs (4)
agent_id(136-138)entrypoint_tag(141-143)new(50-57)new(190-217)runagent-rust/runagent/src/client/runagent_client.rs (4)
agent_id(523-525)entrypoint_tag(528-530)new(97-109)new(194-295)
runagent-rust/examples/async_example.rs (3)
runagent-rust/examples/direct_construction.rs (1)
main(9-27)runagent-rust/examples/sync_example.rs (1)
main(9-26)runagent-rust/runagent/src/client/runagent_client.rs (4)
agent_id(523-525)entrypoint_tag(528-530)new(97-109)new(194-295)
runagent-rust/runagent/examples/direct_construction_omitted.rs (2)
runagent-rust/runagent/examples/direct_construction.rs (1)
main(9-27)runagent-rust/runagent/src/client/runagent_client.rs (3)
new(97-109)new(194-295)default(115-127)
runagent-rust/runagent/examples/test_deserialize.rs (1)
runagent-rust/runagent/src/utils/serializer.rs (4)
serde_json(41-41)serde_json(68-68)serde_json(92-92)new(15-19)
test_scripts/rust/test_langchain/src/main.rs (1)
runagent-rust/runagent/src/client/runagent_client.rs (4)
new(97-109)new(194-295)agent_id(523-525)default(115-127)
test_scripts/rust/test_letta/src/main.rs (2)
runagent-rust/runagent/src/blocking.rs (3)
new(50-57)new(190-217)agent_id(136-138)runagent-rust/runagent/src/client/runagent_client.rs (4)
new(97-109)new(194-295)agent_id(523-525)default(115-127)
runagent-rust/runagent/src/types/errors.rs (4)
examples/lead-agent/backend-rust/src/main.rs (3)
serde_json(161-161)serde_json(168-168)serde_json(175-175)runagent-rust/runagent/src/client/rest_client.rs (1)
serde_json(71-71)runagent-rust/runagent/src/utils/serializer.rs (3)
serde_json(41-41)serde_json(68-68)serde_json(92-92)runagent-rust/runagent/src/types/responses.rs (1)
error(27-35)
examples/lead-agent/backend-rust/src/main.rs (1)
runagent-rust/runagent/src/client/runagent_client.rs (3)
new(97-109)new(194-295)default(115-127)
test_scripts/rust/test_langgraph/src/main.rs (2)
runagent-rust/runagent/src/blocking.rs (3)
new(50-57)new(190-217)agent_id(136-138)runagent-rust/runagent/src/client/runagent_client.rs (4)
new(97-109)new(194-295)agent_id(523-525)default(115-127)
runagent-rust/runagent/src/client/rest_client.rs (3)
runagent-rust/runagent/src/types/errors.rs (2)
validation(77-81)execution(126-138)runagent-rust/runagent/src/utils/config.rs (1)
base_url(135-137)runagent-rust/runagent/src/types/responses.rs (1)
success(17-25)
test_scripts/rust/test_ag2/src/main.rs (2)
runagent-rust/runagent/src/blocking.rs (3)
new(50-57)new(190-217)agent_id(136-138)runagent-rust/runagent/src/client/runagent_client.rs (4)
new(97-109)new(194-295)agent_id(523-525)default(115-127)
test_scripts/rust/test_agno/src/main.rs (2)
runagent-rust/runagent/src/blocking.rs (2)
new(50-57)new(190-217)runagent-rust/runagent/src/client/runagent_client.rs (3)
new(97-109)new(194-295)default(115-127)
runagent-rust/runagent/src/blocking.rs (3)
runagent-rust/runagent/src/client/runagent_client.rs (12)
new(97-109)new(194-295)run(341-343)run_with_args(346-477)run_stream(480-485)run_stream_with_args(488-507)get_agent_architecture(510-512)health_check(515-520)agent_id(523-525)entrypoint_tag(528-530)extra_params(533-535)is_local(538-540)runagent-rust/runagent/src/client/socket_client.rs (2)
new(25-38)run_stream(71-181)runagent-rust/runagent/src/types/errors.rs (1)
connection(84-88)
test_scripts/rust/test_parlant/src/main.rs (2)
runagent-rust/runagent/src/blocking.rs (3)
new(50-57)new(190-217)agent_id(136-138)runagent-rust/runagent/src/client/runagent_client.rs (4)
new(97-109)new(194-295)agent_id(523-525)default(115-127)
runagent-rust/runagent/src/utils/config.rs (3)
runagent-rust/runagent/src/types/errors.rs (1)
config(119-123)runagent-rust/runagent/src/client/rest_client.rs (1)
default(44-51)runagent-rust/runagent/src/client/socket_client.rs (1)
default(41-55)
test_scripts/rust/test_crewai/src/main.rs (2)
runagent-rust/runagent/src/blocking.rs (3)
new(50-57)new(190-217)agent_id(136-138)runagent-rust/runagent/src/client/runagent_client.rs (4)
new(97-109)new(194-295)agent_id(523-525)default(115-127)
runagent-rust/runagent/examples/direct_construction.rs (1)
runagent-rust/runagent/src/client/runagent_client.rs (2)
new(97-109)new(194-295)
runagent-rust/examples/sync_example.rs (2)
runagent-rust/examples/async_example.rs (1)
main(9-26)runagent-rust/runagent/src/blocking.rs (4)
agent_id(136-138)entrypoint_tag(141-143)new(50-57)new(190-217)
runagent-rust/runagent/examples/async_example.rs (2)
runagent-rust/examples/async_example.rs (1)
main(9-26)runagent-rust/runagent/src/client/runagent_client.rs (4)
agent_id(523-525)entrypoint_tag(528-530)new(97-109)new(194-295)
test_scripts/rust/test_autogen/src/main.rs (2)
runagent-rust/runagent/src/blocking.rs (3)
new(50-57)new(190-217)agent_id(136-138)runagent-rust/runagent/src/client/runagent_client.rs (4)
new(97-109)new(194-295)agent_id(523-525)default(115-127)
runagent-rust/runagent/src/client/runagent_client.rs (7)
runagent-rust/runagent/src/blocking.rs (2)
new(50-57)new(190-217)runagent-rust/runagent/src/lib.rs (3)
new(349-351)with_api_key(365-368)with_base_url(382-385)runagent-rust/runagent/src/client/rest_client.rs (2)
new(21-41)default(44-51)runagent-rust/runagent/src/client/socket_client.rs (2)
new(25-38)default(41-55)runagent-rust/runagent/src/utils/serializer.rs (1)
new(15-19)runagent-rust/runagent/src/utils/config.rs (3)
default(26-36)api_key(130-132)base_url(135-137)runagent-rust/runagent/src/types/errors.rs (2)
config(119-123)validation(77-81)
🪛 LanguageTool
runagent-rust/PUBLISH.md
[style] ~15-~15: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...t/Cargo.toml(workspace) if needed. 3. Update the version badge/examples inrunagent...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🔇 Additional comments (39)
templates/agno/default/simple_assistant.py (1)
33-39: LGTM!The streaming function correctly yields serializable dictionaries with extracted content. The defensive attribute checking is consistent with the non-streaming version and appropriate for a template.
runagent-rust/runagent/Cargo.toml (1)
3-3: Version bump looks consistent with the Rust SDK changesIncrementing the crate version to
0.1.34aligns with the new public API surface introduced in this PR.runagent-rust/runagent/src/types/schema.rs (1)
8-8: Home‑based default DB path is a reasonable improvementDeriving the SQLite file path from the user’s home directory (
~/.runagent/runagent_local.db) instead of a fixed relative path makes the default more stable across working directories. The fallback to.when no home dir is found is also a sensible safe default.No issues from this change on its own.
Also applies to: 283-290
examples/lead-agent/backend-rust/src/main.rs (3)
111-117: Config‑based remote client initialization looks correctUsing
RunAgentClient::new(RunAgentClientConfig { agent_id: RUNAGENT_ID.to_string(), entrypoint_tag: "lead_score_flow".to_string(), local: Some(false), ..RunAgentClientConfig::default() })cleanly adopts the new constructor and relies onRUNAGENT_API_KEYfor credentials as intended for cloud usage. Error handling on initialization is appropriate.
221-227: Local client initialization via RunAgentClientConfig is consistentFor
score_single, constructing the client withlocal: Some(true)and otherwise relying onRunAgentClientConfig::default()matches the intended local‑agent flow and mirrors the remote setup above. Initialization errors are correctly surfaced as 500 responses.
260-272: Updated run() call in score_single preserves behaviorChanging to
client.run(¶ms).awaitwhile keeping the existing 500‑on‑error behavior maintains semantics with the new SDK API. Returningresultdirectly as JSON is appropriate here since the single‑candidate scoring endpoint can expose the SDK’s response format as‑is.examples/lead-agent/lead-score-flow/runagent.config.json (1)
1-31: Agent ID change is structurally fine; ensure it matches the deployed agentOnly
agent_idwas updated, with the rest of the config unchanged. From a schema/format perspective this is fine; just double‑check that this UUID corresponds to the intended deployed agent for the lead-score flow so the example targets the right backend.runagent-rust/examples/sync_example.rs (1)
1-27: LGTM! Clear synchronous example.The blocking API example is well-structured and demonstrates the config-based initialization pattern effectively. The hardcoded
agent_idand local address are appropriate for an example file.runagent-rust/runagent/src/client/mod.rs (1)
8-8: LGTM! API surface extended appropriately.The re-export of
RunAgentClientConfigalongsideRunAgentClientis necessary for the config-driven initialization pattern introduced in this PR.runagent-rust/runagent/examples/async_example.rs (1)
1-27: LGTM! Well-structured async example.The async example properly demonstrates the recommended usage pattern with tokio. The structure and documentation are clear and consistent with the synchronous variant.
runagent-rust/examples/async_example.rs (1)
1-27: LGTM! Consistent async example.The example is well-structured and demonstrates the async API usage clearly. The code is consistent with the other examples in the PR.
runagent-rust/runagent/src/db/service.rs (3)
46-48: LGTM! Environment-driven configuration.The use of
LOCAL_CACHE_DIRECTORYfor default path resolution is a good improvement, allowing users to customize the cache location via environment variable while maintaining a sensible default.
50-54: LGTM! Proper directory creation with error handling.The code correctly ensures the parent directory exists before attempting database operations, with appropriate error context.
22-24: Original deprecation claim is incorrect;dirs::home_dir()is not deprecated.The
dirscrate is actively maintained with releases continuing through version 6.0.0, andhome_dir()is documented and present in the API. The confusion may stem fromstd::env::home_dir()(Rust stdlib), which is deprecated, butdirs::home_dir()is a separate, actively maintained function.The current implementation using
dirs::home_dir()with version 5.0 is appropriate and not subject to deprecation concerns.Likely an incorrect or invalid review comment.
runagent-rust/runagent/src/client/socket_client.rs (2)
103-104: LGTM: Serializer clone for async stream.Cloning the serializer for use in the async stream is the correct approach, as the stream closure needs ownership of the serializer to handle message deserialization.
135-151: Excellent: Unified deserialization logic.The enhanced deserialization logic correctly uses the common
CoreSerializermethods (prepare_for_deserializationanddeserialize_object) to handle various payload formats including{type, payload}structures and JSON-encoded strings. Error handling is appropriate with descriptive messages and stream termination on failure.runagent-rust/runagent/examples/sync_example.rs (1)
1-26: LGTM: Clear blocking API example.The synchronous example demonstrates the blocking API usage well with appropriate configuration for local agent execution. The builder pattern and comments make it easy to understand.
test_scripts/rust/test_agno/src/main.rs (1)
66-81: LGTM: Config-based construction is correct.The active example correctly demonstrates the new
RunAgentClientConfig-based construction pattern with struct literal syntax and..RunAgentClientConfig::default()for unspecified fields.test_scripts/rust/test_letta/src/main.rs (1)
51-78: LGTM: Streaming example with config-based construction.The streaming example correctly uses
RunAgentClientConfigand demonstrates proper stream processing with error handling. The pattern is consistent with the broader SDK migration.test_scripts/rust/test_langgraph/src/main.rs (1)
36-56: LGTM: Config-based construction with complex inputs.The example correctly demonstrates the new config pattern and showcases the SDK's ability to handle complex nested JSON structures as input parameters.
runagent-rust/runagent/src/client/rest_client.rs (3)
223-235: Excellent: Enhanced diagnostic logging and error messages.The added logging and enhanced error messages with URL context will significantly improve debugging when agents are not found. The error message provides actionable guidance to users.
237-248: Good: Structured error handling for missing data.The logic correctly returns data on success and provides a helpful
Executionerror with remediation suggestions when data is unexpectedly missing. The inclusion of the full response in error details aids debugging.
250-290: Excellent: Comprehensive error parsing with fallbacks.The error parsing logic robustly handles multiple response formats:
- Structured error objects with code/message/suggestion
- Plain string errors
- Fallback to message field
- Backward compatibility with responses lacking success field
This provides a much better error experience with actionable information.
test_scripts/rust/test_langchain/src/main.rs (1)
56-80: LGTM: Streaming example with proper config pattern.The streaming example correctly uses
RunAgentClientConfigwith the struct literal initialization pattern. Stream processing and error handling follow best practices.test_scripts/rust/test_parlant/src/main.rs (2)
20-25: Config pattern is correct.The
RunAgentClientConfigconstruction uses the correct struct literal pattern with defaults. This code would work fine once the duplicatemainfunction issue is resolved.
58-63: Consistent config pattern.The second
RunAgentClientConfigusage follows the same correct pattern as the first, demonstrating consistent usage across streaming and non-streaming scenarios.runagent-rust/runagent/src/utils/serializer.rs (1)
33-48: Helper for pre-parsing JSON strings looks goodThe
prepare_for_deserializationhelper cleanly handles JSON-encoded strings vs already-parsed values without altering error behavior, which is appropriate for a preprocessing step.test_scripts/rust/test_ag2/src/main.rs (1)
16-21: Config-based client construction and run/run_stream usage look consistentThe switch to
RunAgentClient::new(RunAgentClientConfig { ... }).await?withrun/run_streamtaking a slice of(key, json!(...))arguments aligns with the new API and keeps the non-streaming and streaming paths consistent.Also applies to: 52-57, 24-29, 59-72
test_scripts/rust/test_crewai/src/main.rs (1)
16-21: CrewAI config usage and argument wiring match the new APIThe migration to
RunAgentClient::new(RunAgentClientConfig { ... }).await?and usingrun/run_streamwith the expectedtopicargument slice looks correct and matches the updated client interface.Also applies to: 24-26, 52-57, 59-74
test_scripts/rust/test_autogen/src/main.rs (1)
16-21: AutoGen non-streaming and streaming paths use the new API correctlyThe client construction via
RunAgentClientConfigand therun/run_streamcalls with a singletaskargument slice are consistent with the updated RunAgentClient API and keep the examples aligned across non-streaming and streaming tests.Also applies to: 24-26, 55-60, 62-77
runagent-rust/runagent/src/lib.rs (2)
18-32: Docs now consistently reflect the config-based client APIAll the updated examples (basic, streaming, local, LangChain, LangGraph) now import
RunAgentClientandRunAgentClientConfigfrom the crate root and construct clients viaRunAgentClient::new(RunAgentClientConfig { ... }).await?, which matches the new public API and should help keep users on the correct pattern.Also applies to: 48-60, 81-94, 110-120, 139-150
281-283: Re-exportingRunAgentClientConfigat the root and in the prelude is helpfulIncluding
RunAgentClientConfigin both the top-level re-export set and thepreludemodule makes the new configuration-based API easy to access and keeps the high-level ergonomics intact.Also applies to: 437-438
runagent-rust/runagent/README.md (1)
247-275: API reference and error-handling description look consistent with the new surfaceThe API reference tables for client creation, configuration builder, and client methods correctly mirror the current public surface (
RunAgentClient::new(config), builder methods,run*,run_stream*,health_check,get_agent_architecture) and theRunAgentError::Execution { .. }variant description aligns with the overall error model introduced elsewhere.Nice concise summary of the SDK surface.
runagent-rust/runagent/src/blocking.rs (2)
41-75: Blocking wrapper design is generally sound and mirrors async APIThe blocking
RunAgentClientwrapper cleanly delegates to the async client viaRuntime::new()andblock_on, exposing a synchronous surface (run,run_with_args,run_stream*,health_check,get_agent_architecture) that matches the async API. This is a reasonable approach for users who can’t or don’t want to adopt async in their apps.
220-226: Iterator implementation is straightforward and matches the blocking contractThe
Iteratorimpl forBlockingStreamthat simply doesself.receiver.recv().ok()is simple and correct for a blocking interface; it will yield items until the sender closes and then terminate cleanly.Looks good.
runagent-rust/runagent/src/client/runagent_client.rs (4)
167-276: Client construction and local/remote resolution look correctThe new
RunAgentClient::new(config):
- Correctly derives
localandenable_registryfrom the config.- Resolves host/port for local agents, using the DB when available and
enable_registryis true, with clear validation errors when host/port are still missing.- Resolves API key and base URL with the expected precedence: config > env vars (
RUNAGENT_API_KEY,RUNAGENT_BASE_URL) >DEFAULT_BASE_URL.- Logs useful information about remote connections and presence/absence of an API key.
- Creates REST and socket clients with appropriate HTTP/WS URLs in both local and remote modes.
The
db_servicefield being always initialized asNoneand marked#[allow(dead_code)]is fine for now given it’s reserved for future use.
340-476: Robust response handling and streaming‑generator detection inrun_with_argsThe new
run_with_argslogic is quite thorough:
- It enforces non‑streaming usage for
_streamentrypoints.- Handles multiple response shapes (
dataas string,data.result_data.data, object payloads, and legacyoutput_data), with generator detection at each level.- Uses the shared
CoreSerializerfor{type, payload}structures and applies a size cap.- Provides clear validation messages suggesting
run_streamwhen a generator object is detected.This should make the client resilient across backend evolutions and helps guide users toward the correct streaming API.
Looks solid.
493-507: Local guardrail for non‑stream entrypoints is consistent with READMEThe
_streamsuffix check inrun_stream_with_args:if !self.entrypoint_tag.ends_with("_stream") { return Err(RunAgentError::validation( "Use run() for non-stream entrypoints".to_string(), )); }correctly prevents accidental misuse of streaming APIs with non‑stream entrypoints and matches the guardrails described in the README.
Nice clear error path.
532-541:extra_paramsaccessor is fine; ensure callers know it’s optional/opaqueExposing
extra_params(&self) -> Option<&HashMap<String, Value>>is straightforward and keeps this field flexible for future use. Just ensure callers treat it as opaque metadata for now (as suggested by the docs) to avoid tight coupling to unstable semantics.No changes needed.
| //! Example showing direct struct construction (TypeScript-like interface) | ||
| //! | ||
| //! This matches the TypeScript SDK pattern where you pass a config object directly. | ||
|
|
||
| use runagent::RunAgentClient; | ||
| use serde_json::json; | ||
|
|
||
| #[tokio::main] | ||
| async fn main() -> runagent::RunAgentResult<()> { | ||
| // Direct struct construction - matches TypeScript interface | ||
| let client = RunAgentClient::new(runagent::RunAgentClientConfig { | ||
| agent_id: "a6977384-6c88-40dc-a629-e6bf077786ae".to_string(), | ||
| entrypoint_tag: "minimal".to_string(), | ||
| api_key: Some("rau_b4dcebdef6386726b08971a1cc968d8a2b77c5834d30f3f5a43bddf065cd95cb".to_string()), | ||
| base_url: Some("http://localhost:8333/".to_string()), | ||
| local: None, | ||
| host: None, | ||
| port: None, | ||
| extra_params: None, | ||
| enable_registry: None, | ||
| }).await?; | ||
|
|
||
| let response = client.run(&[("message", json!("Hello!"))]).await?; | ||
|
|
||
| println!("Response: {}", response); | ||
| Ok(()) | ||
| } |
There was a problem hiding this comment.
Remove hard-coded API key from the example to avoid secret exposure
This example currently embeds a full api_key literal:
api_key: Some("rau_...".to_string()),Committing anything that looks like a real API key (even if test-only) is risky and will train users into copying the pattern. It’s safer to:
- Read the key from an environment variable (e.g.,
std::env::var(ENV_RUNAGENT_API_KEY)) or - Use a placeholder like
None/"YOUR_API_KEY_HERE".to_string()and explain in comments how to configure it.
I’d strongly recommend stripping or rotating any real key before merging.
🤖 Prompt for AI Agents
In runagent-rust/examples/direct_construction.rs around lines 1 to 27, remove
the hard-coded api_key literal and replace it with a non-secret pattern: read
the API key from an environment variable (e.g.,
std::env::var("RUNAGENT_API_KEY")) and pass that value as Some(key) if present,
or use None / a clear placeholder like "YOUR_API_KEY_HERE" when not set; ensure
you handle the Result from env::var (map to Option) or fall back safely so the
example compiles and does not expose secrets.
| api_key: Some("rau_b4dcebdef6386726b08971a1cc968d8a2b77c5834d30f3f5a43bddf065cd95cb".to_string()), | ||
| base_url: Some("http://localhost:8333/".to_string()), |
There was a problem hiding this comment.
Remove hardcoded credentials from examples.
Hardcoded API keys and base URLs in example code can be accidentally copied into production. Even if these are test credentials, examples should demonstrate secure practices.
Consider one of these approaches:
- api_key: Some("rau_b4dcebdef6386726b08971a1cc968d8a2b77c5834d30f3f5a43bddf065cd95cb".to_string()),
- base_url: Some("http://localhost:8333/".to_string()),
+ api_key: std::env::var("RUNAGENT_API_KEY").ok(),
+ base_url: std::env::var("RUNAGENT_BASE_URL").ok(),Or use placeholder comments:
- api_key: Some("rau_b4dcebdef6386726b08971a1cc968d8a2b77c5834d30f3f5a43bddf065cd95cb".to_string()),
- base_url: Some("http://localhost:8333/".to_string()),
+ api_key: None, // Or std::env::var("RUNAGENT_API_KEY").ok()
+ base_url: None, // Or Some("http://localhost:8333/".to_string()) for local testing📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| api_key: Some("rau_b4dcebdef6386726b08971a1cc968d8a2b77c5834d30f3f5a43bddf065cd95cb".to_string()), | |
| base_url: Some("http://localhost:8333/".to_string()), | |
| api_key: std::env::var("RUNAGENT_API_KEY").ok(), | |
| base_url: std::env::var("RUNAGENT_BASE_URL").ok(), |
🤖 Prompt for AI Agents
In runagent-rust/runagent/examples/direct_construction_omitted.rs around lines
14 to 15, the example contains hardcoded API key and base URL; remove those
literals and replace them with secure placeholders or runtime configuration
(e.g., read from environment variables like RAGENT_API_KEY and RAGENT_BASE_URL
with a clear placeholder fallback or unwrap_or_else that prompts the user),
update the example to show how to obtain values securely (document the env var
names in a comment) and ensure no secrets are committed in the example code.
| api_key: Some("rau_b4dcebdef6386726b08971a1cc968d8a2b77c5834d30f3f5a43bddf065cd95cb".to_string()), | ||
| base_url: Some("http://localhost:8333/".to_string()), |
There was a problem hiding this comment.
Remove hardcoded credentials from examples.
Same issue as in direct_construction_omitted.rs. Hardcoded API keys in examples can be accidentally copied into production code.
Use environment variables or placeholder comments instead:
- api_key: Some("rau_b4dcebdef6386726b08971a1cc968d8a2b77c5834d30f3f5a43bddf065cd95cb".to_string()),
- base_url: Some("http://localhost:8333/".to_string()),
+ api_key: std::env::var("RUNAGENT_API_KEY").ok(),
+ base_url: std::env::var("RUNAGENT_BASE_URL").ok(),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| api_key: Some("rau_b4dcebdef6386726b08971a1cc968d8a2b77c5834d30f3f5a43bddf065cd95cb".to_string()), | |
| base_url: Some("http://localhost:8333/".to_string()), | |
| api_key: std::env::var("RUNAGENT_API_KEY").ok(), | |
| base_url: std::env::var("RUNAGENT_BASE_URL").ok(), |
🤖 Prompt for AI Agents
In runagent-rust/runagent/examples/direct_construction.rs around lines 14 to 15,
remove the hardcoded API key and any production-like base_url from the example;
replace them with either environment variable reads (e.g., fetch from
std::env::var) or clear placeholder strings and a comment guiding users to set
REAL_API_KEY and REAL_BASE_URL in their environment/config before running.
Ensure the example compiles with placeholders (e.g., Option::None or placeholder
text) and add a brief comment above showing how to export the env vars so
credentials are not embedded in source.
| ```rust | ||
| use runagent::RunAgentClientConfig; | ||
|
|
||
| **Important:** You must export your API key before running your application: | ||
| // Local agent with explicit address | ||
| let client = RunAgentClient::new( | ||
| RunAgentClientConfig::new("agent-id", "entrypoint") | ||
| .with_local(true) | ||
| .with_address("127.0.0.1", 8450) | ||
| .with_enable_registry(false) | ||
| ).await?; | ||
|
|
||
| ```bash | ||
| export RUNAGENT_API_KEY="your-api-key" | ||
| // Remote agent | ||
| let client = RunAgentClient::new( | ||
| RunAgentClientConfig::new("agent-id", "entrypoint") | ||
| .with_api_key(env::var("RUNAGENT_API_KEY").unwrap()) | ||
| ).await?; | ||
| ``` |
There was a problem hiding this comment.
Config overview snippet is missing the RunAgentClient import
In the configuration overview example you use RunAgentClient::new(...) but only import RunAgentClientConfig:
use runagent::RunAgentClientConfig;
// ...
let client = RunAgentClient::new(/* ... */).await?;Add RunAgentClient to the use line so the snippet compiles as shown:
use runagent::{RunAgentClient, RunAgentClientConfig};🤖 Prompt for AI Agents
In runagent-rust/runagent/README.md around lines 31 to 47, the example uses
RunAgentClient::new but only imports RunAgentClientConfig; update the use
statement to import both types so the snippet compiles (i.e., add RunAgentClient
to the use line alongside RunAgentClientConfig).
| ### Local Agents | ||
|
|
||
| For local development, you can configure cache and logging: | ||
| #### With explicit address | ||
|
|
||
| ```bash | ||
| export RUNAGENT_CACHE_DIR="~/.runagent" | ||
| export RUNAGENT_LOGGING_LEVEL="info" | ||
| ```rust | ||
| use runagent::{RunAgentClient, RunAgentClientConfig}; | ||
|
|
||
| let client = RunAgentClient::new(RunAgentClientConfig { | ||
| agent_id: "local-agent-id".to_string(), | ||
| entrypoint_tag: "minimal".to_string(), | ||
| local: Some(true), | ||
| host: Some("127.0.0.1".to_string()), | ||
| port: Some(8452), | ||
| enable_registry: Some(false), // Skip DB lookup | ||
| ..RunAgentClientConfig::default() | ||
| }).await?; | ||
| ``` | ||
|
|
||
| ### Quick Reference | ||
|
|
||
| | Setting | RunAgent Cloud | Local Development | | ||
| |---------|---------------|-------------------| | ||
| | **API Key** | **Required** (`RUNAGENT_API_KEY`) | Not needed | | ||
| | **Base URL** | Optional (defaults to `https://api.runagent.ai`) | Not needed | | ||
| | **Client Parameter** | `local = false` | `local = true` | | ||
| | **Agent Location** | RunAgent infrastructure | Your local machine | | ||
|
|
||
| ### Configuration Builder | ||
|
|
||
| You can also configure the SDK programmatically: | ||
| #### With auto-discovery (requires `db` feature) | ||
|
|
||
| ```rust | ||
| use runagent::RunAgentConfig; | ||
|
|
||
| let config = RunAgentConfig::new() | ||
| .with_api_key("your-api-key") | ||
| .with_base_url("https://api.runagent.ai") | ||
| .with_logging() | ||
| .build(); | ||
| let client = RunAgentClient::new(RunAgentClientConfig { | ||
| agent_id: "local-agent-id".to_string(), | ||
| entrypoint_tag: "minimal".to_string(), | ||
| local: Some(true), | ||
| // enable_registry defaults to true for local agents | ||
| ..RunAgentClientConfig::default() | ||
| }).await?; | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Architecture | ||
|
|
||
| ### Core Components | ||
|
|
||
| * **Client**: High-level client for agent interaction | ||
| * **REST Client**: HTTP-based client for non-streaming requests | ||
| * **Socket Client**: WebSocket-based client for streaming interactions | ||
| * **Database**: SQLite-based agent history store (optional) | ||
| * **Serialization**: Safe messaging via WebSocket | ||
| > **Guardrails**: tags ending with `_stream` can only be run via `run_stream*`. Non-stream tags must be run via `run*`. The client raises clear errors (`STREAM_ENTRYPOINT`, `NON_STREAM_ENTRYPOINT`) with suggestions. |
There was a problem hiding this comment.
Guardrails docs mention specific error codes not clearly surfaced by local validation
The guardrails note promises STREAM_ENTRYPOINT / NON_STREAM_ENTRYPOINT error codes, but the local checks in RunAgentClient::run / run_stream_with_args currently return RunAgentError::validation("Use run_stream for streaming entrypoints" / "Use run() for non-stream entrypoints") without codes.
If those symbolic codes are only produced by the backend (and not by these local guards), consider clarifying the docs, or updating the client-side validation errors to use the same structured Execution variant with codes so behavior matches the table.
🤖 Prompt for AI Agents
In runagent-rust/runagent/README.md around lines 185-215, the docs promise
STREAM_ENTRYPOINT / NON_STREAM_ENTRYPOINT error codes but the client-side local
guards currently return generic validation errors; update the client to return
the same structured Execution/with-code errors as the backend (i.e., have
RunAgentClient::run and run_stream_with_args produce RunAgentError::Execution
including the appropriate code string and helpful message) so behavior matches
the docs, or alternatively update the README text to state that those codes are
only produced by the backend if you prefer not to change code.
| ### Architecture Metadata Contract | ||
| - Treat `/api/v1/agents/{id}/architecture` as an envelope `{ success, data, message, error, timestamp, request_id }`. Handle both the new envelope and the legacy payload transparently. | ||
| - When `success === false`, raise the backend-provided `code/message` and surface any `suggestion`/`details` so users know how to recover (e.g. `AGENT_NOT_FOUND_REMOTE`, `AUTHENTICATION_ERROR`). | ||
| - When `success === true`, normalize `data` into a single `AgentArchitecture` structure that includes `agent_id`/`agentId` plus the full entrypoint metadata (`tag`, `file`, `module`, `extractor`, `description`, etc.). | ||
| - If `data` or `data.entrypoints` is missing, throw a clear `ARCHITECTURE_MISSING` error instructing users to redeploy or supply proper entrypoints. | ||
| - When an entrypoint lookup fails, log or expose the list of entrypoint tags returned by the server to simplify debugging typo/mismatch issues. |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Consolidate duplicated architecture endpoint guidance.
Lines 45–50 and 145–150 both describe the architecture endpoint contract, error handling, and normalization. The Additional Consistency Requirements section largely repeats what's already specified here. Consider consolidating to avoid divergence as the document evolves, or designate one canonical section.
🤖 Prompt for AI Agents
In sdk_checklist.md around lines 45–50, there is duplicated guidance also
present at lines 145–150; consolidate by keeping one canonical "Architecture
Metadata Contract" section (preferably the earlier one at 45–50), remove the
duplicate block at 145–150, and replace it with a short cross-reference pointing
to the canonical section; ensure the canonical section contains the full
requirements (envelope handling, success/error semantics, normalization to
AgentArchitecture, ARCHITECTURE_MISSING error, and entrypoint-tag exposure) so
nothing is lost and update any internal links/TOC entries accordingly.
| - **Run vs. runStream guardrails**: enforce that `_stream` tags only work with `runStream()` (`STREAM_ENTRYPOINT` error with a helpful suggestion) and non-stream tags only work with `run()` (`NON_STREAM_ENTRYPOINT` error). This mirrors the CLI and prevents silent misuse. | ||
| - **Structured error surfaces**: expose a canonical error type (`RunAgentError`/`RunAgentExecutionError`) that always carries `code`, `message`, `suggestion`, and optional `details`, and reuse the shared code taxonomy (`AUTHENTICATION_ERROR`, `PERMISSION_ERROR`, `VALIDATION_ERROR`, `CONNECTION_ERROR`, `SERVER_ERROR`, `AGENT_NOT_FOUND_LOCAL`, `AGENT_NOT_FOUND_REMOTE`, `STREAM_ENTRYPOINT`, `NON_STREAM_ENTRYPOINT`, `ARCHITECTURE_MISSING`, etc.). | ||
| - **Diagnostics for entrypoint mismatches**: when the requested entrypoint isn’t found, log or otherwise expose the set of tags returned by the backend so developers can quickly spot typos or missing deployments. |
There was a problem hiding this comment.
🧩 Analysis chain
Integrate run vs. runStream guardrails and missing error codes into earlier sections.
The run/runStream entrypoint validation and new error codes (STREAM_ENTRYPOINT, NON_STREAM_ENTRYPOINT) should be moved into the "HTTP run() Semantics" (line 57) and "WebSocket run_stream() Semantics" (line 84) sections, where endpoint-specific behavior is already documented. Additionally, these error codes are not mentioned in the error taxonomy (line 82), creating a gap where readers can't find the canonical list.
The phrase "_stream tags" (line 147) should also be defined the first time it appears—introduce it earlier (perhaps in line 4 when discussing entrypoint metadata) to clarify what distinguishes a stream-eligible tag.
Verify that STREAM_ENTRYPOINT, NON_STREAM_ENTRYPOINT, and ARCHITECTURE_MISSING error codes are consistently defined in the canonical error taxonomy and are actually implemented (enforced) in the Rust SDK and other SDKs.
I need to gather information from the codebase to verify this review comment. Let me examine the file and search for the relevant error code implementations.
---
🏁 Script executed:
```shell
#!/bin/bash
# Examine sdk_checklist.md to see current structure and error taxonomy
cat sdk_checklist.md | head -150 | tail -100
Length of output: 6312
🏁 Script executed:
#!/bin/bash
# Search for error code definitions in the file, especially the taxonomy section around line 82
cat sdk_checklist.md | sed -n '70,120p'Length of output: 2671
🏁 Script executed:
#!/bin/bash
# Look for STREAM_ENTRYPOINT, NON_STREAM_ENTRYPOINT, ARCHITECTURE_MISSING in the codebase
rg -n 'STREAM_ENTRYPOINT|NON_STREAM_ENTRYPOINT|ARCHITECTURE_MISSING' -C2Length of output: 6701
🏁 Script executed:
#!/bin/bash
# Search for _stream tags definition in sdk_checklist.md
rg -n '_stream' sdk_checklist.md -C2Length of output: 2926
🏁 Script executed:
#!/bin/bash
# Look for Rust SDK error implementations
fd -e rs | xargs rg -l 'RunAgentError|error.*code' | head -20Length of output: 439
Reorganize error taxonomy and define "_stream tags" to consolidate run/runStream guardrails.
The review comment is accurate: STREAM_ENTRYPOINT, NON_STREAM_ENTRYPOINT, and ARCHITECTURE_MISSING error codes are currently documented only in the "Additional Consistency Requirements" section (line 148), not in the canonical error taxonomy at line 82. The codes are already implemented in Rust and TypeScript SDKs, but the documentation structure creates a gap where readers must cross-reference sections.
Additionally, "_stream tags" lacks a formal definition on first mention (line 147). The term should be introduced when entrypoint metadata is discussed (around line 4).
The suggested refactor is valid and necessary:
- Add
STREAM_ENTRYPOINT,NON_STREAM_ENTRYPOINT, andARCHITECTURE_MISSINGto the error taxonomy at line 82. - Move the run/runStream guardrails content into the "HTTP
run()Semantics" (line 57) and "WebSocketrun_stream()Semantics" (line 84) sections to document endpoint-specific validation behavior where it belongs. - Define "_stream tags" early (line 4 context) as entrypoint tags ending with
_streamthat invoke streaming behavior.
🤖 Prompt for AI Agents
In sdk_checklist.md around lines 147-149, the review points out that
STREAM_ENTRYPOINT, NON_STREAM_ENTRYPOINT, and ARCHITECTURE_MISSING are only
documented in "Additional Consistency Requirements" instead of the canonical
error taxonomy; add these three error codes to the error taxonomy at ~line 82;
define “_stream tags” early near the entrypoint metadata discussion (~line 4) as
tags that end with “_stream” and invoke streaming behavior; move the
run/runStream guardrails text from the Additional Consistency section into the
HTTP `run()` Semantics (~line 57) and WebSocket `run_stream()` Semantics (~line
84) sections so endpoint-specific validation is documented in-place; finally,
include the diagnostics recommendation in the entrypoint-mismatch guidance to
log/expose the set of tags returned by the backend when an entrypoint isn’t
found.
| ### Additional Consistency Requirements | ||
| - **Architecture endpoint contract**: every SDK must treat `/api/v1/agents/{id}/architecture` as an envelope `{ success, data, message, error, timestamp, request_id }`, propagate backend `error.code/message/suggestion/details`, normalize the `data` payload (including `agent_id`/`agentId`, `file`, `module`, `extractor`, etc.), and throw a clear `ARCHITECTURE_MISSING` error when `data.entrypoints` is absent. | ||
| - **Run vs. runStream guardrails**: enforce that `_stream` tags only work with `runStream()` (`STREAM_ENTRYPOINT` error with a helpful suggestion) and non-stream tags only work with `run()` (`NON_STREAM_ENTRYPOINT` error). This mirrors the CLI and prevents silent misuse. | ||
| - **Structured error surfaces**: expose a canonical error type (`RunAgentError`/`RunAgentExecutionError`) that always carries `code`, `message`, `suggestion`, and optional `details`, and reuse the shared code taxonomy (`AUTHENTICATION_ERROR`, `PERMISSION_ERROR`, `VALIDATION_ERROR`, `CONNECTION_ERROR`, `SERVER_ERROR`, `AGENT_NOT_FOUND_LOCAL`, `AGENT_NOT_FOUND_REMOTE`, `STREAM_ENTRYPOINT`, `NON_STREAM_ENTRYPOINT`, `ARCHITECTURE_MISSING`, etc.). |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Deduplicate structured error handling guidance.
Lines 148 and 110–113 both describe error types and structured surfaces. Consolidate into a single, authoritative "Error Handling Guidance" section to avoid maintenance drift.
🤖 Prompt for AI Agents
In sdk_checklist.md around line 148 (and duplicated content at lines 110–113),
there are two overlapping descriptions of structured error types; consolidate
them into a single authoritative "Error Handling Guidance" section: merge the
duplicated text into one canonical paragraph that defines the
RunAgentError/RunAgentExecutionError shape (code, message, suggestion, optional
details), include the shared code taxonomy (AUTHENTICATION_ERROR,
PERMISSION_ERROR, VALIDATION_ERROR, CONNECTION_ERROR, SERVER_ERROR,
AGENT_NOT_FOUND_LOCAL, AGENT_NOT_FOUND_REMOTE, STREAM_ENTRYPOINT,
NON_STREAM_ENTRYPOINT, ARCHITECTURE_MISSING, etc.), remove the duplicate block
at lines 110–113, and replace it with a short cross-reference to the unified
section to avoid drift.
| "agent_name": "Agno agent simple assistant", | ||
| "description": "My AI agent simple assistant", | ||
| "framework": "agno", |
There was a problem hiding this comment.
🧩 Analysis chain
Verify agent_id consistency with clients using this template
The updated agent_name/description (“simple assistant”) look good.
However, this config’s agent_id (ae29bd73-b3d3-42c8-a98f-5d7aec7ee919) differs from the one used in test_scripts/python/client_test_agno.py (ad29...). If that script is intended to target this template’s agent, it would be good to make the IDs consistent.
Please confirm whether they should point at the same agent and adjust accordingly.
Also applies to: 28-31
🏁 Script executed:
#!/bin/bash
# Find and display agent_id from runagent.config.json
echo "=== runagent.config.json agent_id ==="
find . -name "runagent.config.json" -type f -exec grep -n "agent_id" {} + 2>/dev/null | head -20
echo -e "\n=== client_test_agno.py agent references ==="
find . -name "client_test_agno.py" -type f -exec grep -n "agent_id\|ad29\|ae29" {} + 2>/dev/null | head -20Length of output: 2325
Confirm and align agent_id between template and test client
The agent_id in templates/agno/default/runagent.config.json:28 is ae29bd73-b3d3-42c8-a98f-5d7aec7ee919, but test_scripts/python/client_test_agno.py:20 uses ad29bd73-b3d3-42c8-a98f-5d7aec7ee919 (note the difference in the 3rd–4th characters: ae29 vs ad29). If this test client is meant to work with this template, align the IDs to match.
🤖 Prompt for AI Agents
In templates/agno/default/runagent.config.json around lines 2–28 the agent_id
value (currently ae29bd73-b3d3-42c8-a98f-5d7aec7ee919) does not match the
agent_id used in test_scripts/python/client_test_agno.py line 20
(ad29bd73-b3d3-42c8-a98f-5d7aec7ee919); update one of these files so both use
the exact same UUID (choose which is canonical for your tests and replace the
mismatched UUID accordingly) to ensure the test client targets the template
agent.
| ra = RunAgentClient( | ||
| agent_id="abc4f000-0000-0000-0000-000000000000", | ||
| agent_id="ad29bd73-b3d3-42c8-a98f-5d7aec7ee919", | ||
| entrypoint_tag="agno_print_response_stream", | ||
| local=False | ||
| ) |
There was a problem hiding this comment.
🧩 Analysis chain
Possible agent_id mismatch with template configuration
The agent_id here is ad29bd73-b3d3-42c8-a98f-5d7aec7ee919, while templates/agno/default/runagent.config.json uses ae29bd73-b3d3-42c8-a98f-5d7aec7ee919. The one-character difference (d vs e) looks unintentional.
Please double-check which ID is correct and align the script and template so they target the same agent.
🏁 Script executed:
#!/bin/bash
# Verify test script exists and check lines 19-23
echo "=== Checking test script ==="
if [ -f "test_scripts/python/client_test_agno.py" ]; then
echo "File exists. Lines 19-23:"
sed -n '19,23p' "test_scripts/python/client_test_agno.py"
else
echo "File NOT found"
fi
# Verify template config exists and search for agent_id
echo -e "\n=== Checking template config ==="
if [ -f "templates/agno/default/runagent.config.json" ]; then
echo "File exists. Full content:"
cat "templates/agno/default/runagent.config.json"
else
echo "File NOT found"
fi
# Search for all occurrences of both agent IDs in codebase
echo -e "\n=== Searching for agent ID: ad29bd73-b3d3-42c8-a98f-5d7aec7ee919 ==="
rg "ad29bd73-b3d3-42c8-a98f-5d7aec7ee919" -n
echo -e "\n=== Searching for agent ID: ae29bd73-b3d3-42c8-a98f-5d7aec7ee919 ==="
rg "ae29bd73-b3d3-42c8-a98f-5d7aec7ee919" -nLength of output: 1909
Confirm agent_id mismatch and align test script with template
Verification confirms the mismatch: the Python test script uses ad29bd73-b3d3-42c8-a98f-5d7aec7ee919, while the template config uses ae29bd73-b3d3-42c8-a98f-5d7aec7ee919 (differ by one character: d vs e). The Rust test also indicates the ae29... version is the canonical agent ID (used in active code and template). Update test_scripts/python/client_test_agno.py line 20 to use ae29bd73-b3d3-42c8-a98f-5d7aec7ee919 to align with the configured agent.
🤖 Prompt for AI Agents
In test_scripts/python/client_test_agno.py around lines 19 to 23, the agent_id
value is incorrect (uses ad29bd73-... with 'd'); update the agent_id on line 20
to the canonical ae29bd73-b3d3-42c8-a98f-5d7aec7ee919 so the Python test matches
the template and Rust test; save and run tests to verify alignment.
New rust sdk comes with sync and async of both streaming and non streaming as well as fixed the argument for both streaming and non streaming. Now runs with run and run_stream
Summary by CodeRabbit
New Features
Documentation
Chores