Skip to content

Commit 46808d8

Browse files
author
Symbiont OSS Sync
committed
Add remaining http-api endpoints and docs
1 parent c552c8f commit 46808d8

15 files changed

+1747
-206
lines changed

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[中文简体](README.zh-cn.md) | [Español](README.es.md) | [Português](README.pt.md) | [日本語](README.ja.md) | [Deutsch](README.de.md)
44

5-
**Symbi** is an AI-native agent framework for building autonomous, policy-aware agents that can safely collaborate with humans, other agents, and large language models. The Community edition provides core functionality with optional Enterprise features for advanced security, monitoring, and collaboration.
5+
**Symbi** is an AI-native agent framework for building autonomous, policy-aware agents that can safely collaborate with humans, other agents, and large language models.
66

77
## 🚀 Quick Start
88

@@ -66,10 +66,19 @@ symbi-runtime = { version = "0.1.2", features = ["http-api"] }
6666
6767
**Key Endpoints:**
6868
- `GET /api/v1/health` - Health check and system status
69-
- `GET /api/v1/agents` - List all active agents
69+
- `GET /api/v1/agents` - List all active agents (requires authentication)
70+
- `GET /api/v1/agents/{id}/status` - Get specific agent status (requires authentication)
71+
- `POST /api/v1/agents` - Create a new agent (requires authentication)
72+
- `PUT /api/v1/agents/{id}` - Update an agent (requires authentication)
73+
- `DELETE /api/v1/agents/{id}` - Delete an agent (requires authentication)
74+
- `POST /api/v1/agents/{id}/execute` - Execute an agent (requires authentication)
75+
- `GET /api/v1/agents/{id}/history` - Get agent execution history (requires authentication)
7076
- `POST /api/v1/workflows/execute` - Execute workflows
7177
- `GET /api/v1/metrics` - System metrics
7278
79+
> **Note:** All `/api/v1/agents*` endpoints require Bearer token authentication. Set the `API_AUTH_TOKEN` environment variable and use the header:
80+
> `Authorization: Bearer <your-token>`
81+
7382
## 📁 Project Structure
7483
7584
```

crates/runtime/README.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ The Symbi Agent Runtime System provides a complete infrastructure for executing
2626
## Architecture
2727

2828
```
29-
┌─────────────────────────────────────────────────────────────────────────────┐
30-
│ Agent Runtime System │
29+
┌───────────────────────────────────────────────────────────────────────────────
30+
│ Agent Runtime System
3131
├─────────────────┬─────────────────┬─────────────────┬─────────────────────────┤
3232
│ Scheduler │ Lifecycle │ Resource Manager│ Context Manager │
3333
│ │ Controller │ │ │
@@ -38,8 +38,8 @@ The Symbi Agent Runtime System provides a complete infrastructure for executing
3838
│ MCP Client │ SchemaPin │ Tool Review │ Policy Engine │
3939
│ │ Integration │ Workflow │ │
4040
├─────────────────┼─────────────────┼─────────────────┼─────────────────────────┤
41-
│ HTTP API Server │ │ │ (Optional) │
42-
│ (Optional) │ │ │ │
41+
│ HTTP API Server │ HTTP-Input │ │ (Optional) │
42+
│ (Optional) │ (Optional) │ │ │
4343
└─────────────────┴─────────────────┴─────────────────┴─────────────────────────┘
4444
```
4545

@@ -438,11 +438,19 @@ api_server.start().await?;
438438
#### Available Endpoints
439439

440440
- `GET /api/v1/health` - System health check
441-
- `GET /api/v1/agents` - List all active agents
442-
- `GET /api/v1/agents/{id}/status` - Get specific agent status
441+
- `GET /api/v1/agents` - List all active agents (requires authentication)
442+
- `GET /api/v1/agents/{id}/status` - Get specific agent status (requires authentication)
443+
- `POST /api/v1/agents` - Create a new agent (requires authentication)
444+
- `PUT /api/v1/agents/{id}` - Update an agent (requires authentication)
445+
- `DELETE /api/v1/agents/{id}` - Delete an agent (requires authentication)
446+
- `POST /api/v1/agents/{id}/execute` - Execute an agent (requires authentication)
447+
- `GET /api/v1/agents/{id}/history` - Get agent execution history (requires authentication)
443448
- `POST /api/v1/workflows/execute` - Execute workflows
444449
- `GET /api/v1/metrics` - System performance metrics
445450

451+
> **Note:** All `/api/v1/agents*` endpoints require Bearer token authentication. Set the `API_AUTH_TOKEN` environment variable and use the header:
452+
> `Authorization: Bearer <your-token>`
453+
446454
#### Example Usage
447455

448456
```bash

crates/runtime/src/api/middleware.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,37 @@
66
#[cfg(feature = "http-api")]
77
use axum::{extract::Request, http::StatusCode, middleware::Next, response::Response};
88

9-
/// Authentication middleware (placeholder)
9+
/// Authentication middleware for bearer token validation
1010
#[cfg(feature = "http-api")]
1111
pub async fn auth_middleware(request: Request, next: Next) -> Result<Response, StatusCode> {
12-
// TODO: Implement actual authentication logic
13-
// For now, just pass through all requests
12+
// Extract the Authorization header
13+
let headers = request.headers();
14+
let auth_header = headers.get("authorization");
15+
16+
// Check if Authorization header is present
17+
let auth_value = match auth_header {
18+
Some(value) => value.to_str().map_err(|_| StatusCode::UNAUTHORIZED)?,
19+
None => return Err(StatusCode::UNAUTHORIZED),
20+
};
21+
22+
// Check if it's a Bearer token
23+
if !auth_value.starts_with("Bearer ") {
24+
return Err(StatusCode::UNAUTHORIZED);
25+
}
26+
27+
// Extract the token part (after "Bearer ")
28+
let token = &auth_value[7..];
29+
30+
// Get the expected token from environment variable
31+
let expected_token = std::env::var("API_AUTH_TOKEN")
32+
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
33+
34+
// Validate the token
35+
if token != expected_token {
36+
return Err(StatusCode::UNAUTHORIZED);
37+
}
38+
39+
// Token is valid, proceed with the request
1440
Ok(next.run(request).await)
1541
}
1642

crates/runtime/src/api/routes.rs

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::sync::Arc;
1616
use super::traits::RuntimeApiProvider;
1717

1818
#[cfg(feature = "http-api")]
19-
use super::types::{AgentStatusResponse, ErrorResponse, WorkflowExecutionRequest};
19+
use super::types::{AgentStatusResponse, CreateAgentRequest, CreateAgentResponse, DeleteAgentResponse, ErrorResponse, ExecuteAgentRequest, ExecuteAgentResponse, GetAgentHistoryResponse, UpdateAgentRequest, UpdateAgentResponse, WorkflowExecutionRequest};
2020

2121
#[cfg(feature = "http-api")]
2222
use crate::types::AgentId;
@@ -99,3 +99,100 @@ pub async fn get_metrics(
9999
)),
100100
}
101101
}
102+
103+
/// Create agent endpoint handler
104+
#[cfg(feature = "http-api")]
105+
pub async fn create_agent(
106+
State(provider): State<Arc<dyn RuntimeApiProvider>>,
107+
Json(request): Json<CreateAgentRequest>,
108+
) -> Result<Json<CreateAgentResponse>, (StatusCode, Json<ErrorResponse>)> {
109+
match provider.create_agent(request).await {
110+
Ok(response) => Ok(Json(response)),
111+
Err(e) => Err((
112+
StatusCode::INTERNAL_SERVER_ERROR,
113+
Json(ErrorResponse {
114+
error: e.to_string(),
115+
code: "AGENT_CREATION_FAILED".to_string(),
116+
details: None,
117+
}),
118+
)),
119+
}
120+
}
121+
122+
/// Update agent endpoint handler
123+
#[cfg(feature = "http-api")]
124+
pub async fn update_agent(
125+
State(provider): State<Arc<dyn RuntimeApiProvider>>,
126+
Path(agent_id): Path<String>,
127+
Json(request): Json<UpdateAgentRequest>,
128+
) -> Result<Json<UpdateAgentResponse>, (StatusCode, Json<ErrorResponse>)> {
129+
match provider.update_agent(agent_id, request).await {
130+
Ok(response) => Ok(Json(response)),
131+
Err(e) => Err((
132+
StatusCode::INTERNAL_SERVER_ERROR,
133+
Json(ErrorResponse {
134+
error: e.to_string(),
135+
code: "AGENT_UPDATE_FAILED".to_string(),
136+
details: None,
137+
}),
138+
)),
139+
}
140+
}
141+
142+
/// Delete agent endpoint handler
143+
#[cfg(feature = "http-api")]
144+
pub async fn delete_agent(
145+
State(provider): State<Arc<dyn RuntimeApiProvider>>,
146+
Path(agent_id): Path<String>,
147+
) -> Result<Json<DeleteAgentResponse>, (StatusCode, Json<ErrorResponse>)> {
148+
match provider.delete_agent(agent_id).await {
149+
Ok(response) => Ok(Json(response)),
150+
Err(e) => Err((
151+
StatusCode::INTERNAL_SERVER_ERROR,
152+
Json(ErrorResponse {
153+
error: e.to_string(),
154+
code: "AGENT_DELETION_FAILED".to_string(),
155+
details: None,
156+
}),
157+
)),
158+
}
159+
}
160+
161+
/// Execute agent endpoint handler
162+
#[cfg(feature = "http-api")]
163+
pub async fn execute_agent(
164+
State(provider): State<Arc<dyn RuntimeApiProvider>>,
165+
Path(agent_id): Path<String>,
166+
Json(request): Json<ExecuteAgentRequest>,
167+
) -> Result<Json<ExecuteAgentResponse>, (StatusCode, Json<ErrorResponse>)> {
168+
match provider.execute_agent(agent_id, request).await {
169+
Ok(response) => Ok(Json(response)),
170+
Err(e) => Err((
171+
StatusCode::INTERNAL_SERVER_ERROR,
172+
Json(ErrorResponse {
173+
error: e.to_string(),
174+
code: "AGENT_EXECUTION_FAILED".to_string(),
175+
details: None,
176+
}),
177+
)),
178+
}
179+
}
180+
181+
/// Get agent execution history endpoint handler
182+
#[cfg(feature = "http-api")]
183+
pub async fn get_agent_history(
184+
State(provider): State<Arc<dyn RuntimeApiProvider>>,
185+
Path(agent_id): Path<String>,
186+
) -> Result<Json<GetAgentHistoryResponse>, (StatusCode, Json<ErrorResponse>)> {
187+
match provider.get_agent_history(agent_id).await {
188+
Ok(response) => Ok(Json(response)),
189+
Err(e) => Err((
190+
StatusCode::INTERNAL_SERVER_ERROR,
191+
Json(ErrorResponse {
192+
error: e.to_string(),
193+
code: "AGENT_HISTORY_FAILED".to_string(),
194+
details: None,
195+
}),
196+
)),
197+
}
198+
}

crates/runtime/src/api/server.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,33 @@ impl HttpApiServer {
9292

9393
/// Create the Axum router with all routes and middleware
9494
fn create_router(&self) -> Router {
95-
use axum::routing::{get, post};
95+
use axum::routing::{get, post, put};
9696

9797
let mut router = Router::new().route("/api/v1/health", get(health_check));
9898

9999
// Add stateful routes if we have a runtime provider
100100
if let Some(provider) = &self.runtime_provider {
101-
use super::routes::{execute_workflow, get_agent_status, list_agents, get_metrics};
101+
use super::routes::{create_agent, delete_agent, execute_agent, execute_workflow, get_agent_history, get_agent_status, list_agents, get_metrics, update_agent};
102+
use super::middleware::auth_middleware;
103+
use axum::middleware;
102104

103-
let stateful_router = Router::new()
104-
.route("/api/v1/workflows/execute", post(execute_workflow))
105-
.route("/api/v1/agents", get(list_agents))
105+
// Agent routes that require authentication
106+
let agent_router = Router::new()
107+
.route("/api/v1/agents", get(list_agents).post(create_agent))
106108
.route("/api/v1/agents/:id/status", get(get_agent_status))
109+
.route("/api/v1/agents/:id", put(update_agent).delete(delete_agent))
110+
.route("/api/v1/agents/:id/execute", post(execute_agent))
111+
.route("/api/v1/agents/:id/history", get(get_agent_history))
112+
.layer(middleware::from_fn(auth_middleware))
113+
.with_state(provider.clone());
114+
115+
// Other routes without authentication
116+
let other_router = Router::new()
117+
.route("/api/v1/workflows/execute", post(execute_workflow))
107118
.route("/api/v1/metrics", get(get_metrics))
108119
.with_state(provider.clone());
109120

110-
router = router.merge(stateful_router);
121+
router = router.merge(agent_router).merge(other_router);
111122
}
112123

113124
// Add middleware conditionally

crates/runtime/src/api/traits.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use async_trait::async_trait;
1010
use crate::types::{AgentId, RuntimeError};
1111

1212
#[cfg(feature = "http-api")]
13-
use super::types::{AgentStatusResponse, WorkflowExecutionRequest};
13+
use super::types::{AgentStatusResponse, CreateAgentRequest, CreateAgentResponse, DeleteAgentResponse, ExecuteAgentRequest, ExecuteAgentResponse, GetAgentHistoryResponse, UpdateAgentRequest, UpdateAgentResponse, WorkflowExecutionRequest};
1414

1515
/// Trait providing API access to core runtime functionalities
1616
#[cfg(feature = "http-api")]
@@ -39,4 +39,36 @@ pub trait RuntimeApiProvider: Send + Sync {
3939

4040
/// Get runtime system metrics
4141
async fn get_metrics(&self) -> Result<serde_json::Value, RuntimeError>;
42+
43+
/// Create a new agent with the given configuration
44+
async fn create_agent(
45+
&self,
46+
request: CreateAgentRequest,
47+
) -> Result<CreateAgentResponse, RuntimeError>;
48+
49+
/// Update an existing agent with the given configuration
50+
async fn update_agent(
51+
&self,
52+
agent_id: String,
53+
request: UpdateAgentRequest,
54+
) -> Result<UpdateAgentResponse, RuntimeError>;
55+
56+
/// Delete an existing agent
57+
async fn delete_agent(
58+
&self,
59+
agent_id: String,
60+
) -> Result<DeleteAgentResponse, RuntimeError>;
61+
62+
/// Execute an agent with the given request
63+
async fn execute_agent(
64+
&self,
65+
agent_id: String,
66+
request: ExecuteAgentRequest,
67+
) -> Result<ExecuteAgentResponse, RuntimeError>;
68+
69+
/// Get execution history for an agent
70+
async fn get_agent_history(
71+
&self,
72+
agent_id: String,
73+
) -> Result<GetAgentHistoryResponse, RuntimeError>;
4274
}

0 commit comments

Comments
 (0)