Skip to main content

clawdesk-gateway

The HTTP and WebSocket gateway server built on Axum. Exposes the REST API, OpenAI-compatible endpoints, WebSocket streaming, and admin endpoints. This is the main application server crate.

Dependencies

Internal: clawdesk-types, clawdesk-domain, clawdesk-storage, clawdesk-agents, clawdesk-providers, clawdesk-channel, clawdesk-channels, clawdesk-plugin, clawdesk-security, clawdesk-cron, clawdesk-skills, clawdesk-observability

External: axum, tokio, tower, serde, tracing, uuid, arc-swap

Modules

ModuleDescription
adminAdmin API endpoints (plugins, cron, skills, channels, metrics)
bootstrapServer startup, dependency wiring, graceful shutdown
middlewareAuthentication, logging, rate limiting, CORS middleware
openai_compatOpenAI-compatible /v1/chat/completions and /v1/models
rate_limiterRequest rate limiting per session/IP
responses_apiResponses API endpoints (/v1/responses)
routesCore REST API route definitions (/api/v1/*)
rpcInternal RPC for inter-service communication
skills_adminSkill management admin endpoints
stateAppState — shared application state
watcherConfig file watcher for hot-reload
wsWebSocket upgrade handler and message routing

Key Types

/// Shared application state passed to all handlers
pub struct AppState {
pub pipeline: Arc<Pipeline>,
pub session_store: Arc<dyn SessionStore>,
pub conversation_store: Arc<dyn ConversationStore>,
pub config: Arc<ArcSwap<AppConfig>>,
pub provider_registry: Arc<ProviderRegistry>,
pub channel_registry: Arc<ChannelRegistry>,
pub plugin_registry: Arc<PluginRegistry>,
pub skill_registry: Arc<SkillRegistry>,
pub cron_manager: Arc<CronManager>,
}

/// Build the Axum router with all routes
pub fn build_router(state: AppState) -> Router {
Router::new()
// Core API
.route("/api/v1/health", get(health))
.route("/api/v1/message", post(send_message))
.route("/api/v1/sessions", get(list_sessions))
.route("/api/v1/sessions/:id", get(get_session).delete(delete_session))
.route("/api/v1/sessions/:id/messages", get(get_messages))
.route("/api/v1/sessions/:id/compact", post(compact_session))
.route("/api/v1/channels", get(list_channels))
.route("/api/v1/config", get(get_config))
.route("/api/v1/models", get(list_models))
// OpenAI-compatible
.route("/v1/chat/completions", post(chat_completions))
.route("/v1/models", get(openai_models))
.route("/v1/responses", post(create_response))
.route("/v1/responses/:id", get(get_response))
// Admin
.nest("/api/v1/admin", admin_routes())
// WebSocket
.route("/ws", get(ws_upgrade))
.with_state(state)
}

Example Usage

use clawdesk_gateway::{bootstrap, AppState};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Bootstrap wires all dependencies together
let state = bootstrap::initialize().await?;

let router = clawdesk_gateway::build_router(state);

let listener = tokio::net::TcpListener::bind("0.0.0.0:1420").await?;
axum::serve(listener, router)
.with_graceful_shutdown(shutdown_signal())
.await?;

Ok(())
}
tip

The gateway supports hot-reload of configuration via the file watcher. Changes to config.toml are picked up without restart using ArcSwap.