Corbusier orchestrates agent turns through a single service path that validates
the target backend, resolves or rotates a backend runtime session, executes the
turn, and routes tool calls in deterministic order. Session continuity is
tracked per (tenant_id, backend_id, conversation_id) until the session
expires, with every repository query binding RequestContext.tenant_id so
tenant isolation is enforced for reuse and rotation.
When a stored session is still active within the current tenant, it is reused.
When expired, the session is marked expired and a new runtime session is
created automatically. The session repository commits a reserved slot row for
the current tenant before the runtime session is created, so expiry detection,
replacement-session claiming, and subsequent reuse all remain tenant-scoped and
happen at the database boundary before any external runtime call is made.
use std::sync::Arc;
use corbusier::agent_backend::{
adapters::memory::{
InMemoryAgentRuntime, InMemoryBackendRegistry, InMemoryToolRouter,
InMemoryTurnSessionRepository,
},
domain::{BackendId, ToolCallRequest, TurnExecutionRequest, TurnExecutionResult},
ports::BackendRegistryRepository,
services::{
AgentTurnOrchestratorPorts, AgentTurnOrchestratorService, ExecuteAgentTurnRequest,
},
};
use chrono::Duration;
use corbusier::context::{CorrelationId, RequestContext, SessionId, TenantId, UserId};
use mockable::DefaultClock;
use serde_json::json;
use uuid::Uuid;
async fn execute_orchestrated_turn() -> Result<(), Box<dyn std::error::Error>> {
let registry = Arc::new(InMemoryBackendRegistry::new());
let sessions = Arc::new(InMemoryTurnSessionRepository::new());
let runtime = Arc::new(InMemoryAgentRuntime::new());
let router = Arc::new(InMemoryToolRouter::new());
let clock = Arc::new(DefaultClock);
let ctx = RequestContext::new(
TenantId::new(),
CorrelationId::new(),
UserId::new(),
SessionId::new(),
);
// Register one backend used for orchestration.
let backend = corbusier::agent_backend::services::BackendRegistryService::new(
registry.clone(),
clock.clone(),
)
.register(
&ctx,
corbusier::agent_backend::services::RegisterBackendRequest::new(
"claude_code_sdk",
"Claude Code SDK",
"1.0.0",
"Anthropic",
)
.with_capabilities(true, true),
)
.await?;
// Configure runtime and tool router behaviour for demonstration.
runtime.queue_turn_result(TurnExecutionResult::new(
"assistant response",
vec![ToolCallRequest::new("search_docs", json!({"query": "roadmap"}))?],
))?;
router.set_tool_response("search_docs", json!({"matches": 3}))?;
let orchestrator = AgentTurnOrchestratorService::with_config(
AgentTurnOrchestratorPorts {
backend_registry: registry,
turn_sessions: sessions,
runtime,
tool_router: router,
clock,
},
corbusier::agent_backend::services::AgentTurnOrchestratorConfig::new(
Duration::minutes(5),
)?,
);
let response = orchestrator
.execute_turn(
&ctx,
ExecuteAgentTurnRequest::new(
BackendId::from_uuid(backend.id().into_inner()),
TurnExecutionRequest::new(Uuid::new_v4(), "Please summarize this", Vec::new()),
),
)
.await?;
assert_eq!(response.tool_results().len(), 1);
assert!(!response.rotated_session());
Ok(())
}
Build standard
Development builds (make test, make lint, make typecheck and the debug
build) use the parallel rustc frontend (-Zthreads=8) and, on Linux, the
mold linker. Install mold before building on Linux: the configuration names
it, so a build without it fails at link time.
The flags live in .cargo/config.toml, but Cargo applies exactly one
rustflags source and an assigned RUSTFLAGS replaces every configuration
source. The Makefile therefore restates the flags in each recipe and keeps any
RUSTFLAGS already in the environment, appending the standard flags after it.
Two builds are held out deliberately. The coverage build assigns its own flags,
because a measurement should not depend on the fast flags. make release keeps
the environment's RUSTFLAGS and names neither fast flag, so a shipped
artefact links with the platform linker. A bare cargo build --release takes
the configuration's flags unless RUSTFLAGS is assigned, for example
RUSTFLAGS="" cargo build --release.
Cranelift is the development-profile code generator, selected in
.cargo/config.toml; coverage selects LLVM explicitly because instrumentation
needs it. See ADR 012 for the reasoning.