| Crates.io | axor |
| lib.rs | axor |
| version | 0.1.2 |
| created_at | 2025-06-11 13:37:54.371035+00 |
| updated_at | 2025-06-13 14:56:23.258201+00 |
| description | Core of the Axor framework: agent-based business logic with typed operations and injection. |
| homepage | |
| repository | https://github.com/kinai-io/axor |
| max_upload_size | |
| id | 1708598 |
| size | 25,790 |
Axor is a zero-overhead, modular backend framework based on agents.
It helps you structure your backend logic into isolated, injectable components — called agents — that expose typed operations and can be invoked either directly or dynamically via RPC.
“Give me six hours to chop down a tree and I will spend the first four sharpening the axe.”
— Abraham Lincoln
Axor is your sharpened axe: focus on business logic, not boilerplate.
✅ Clean design
🧪 No ceremony
🚀 Zero runtime cost when calling directly
🌐 RPC-style invocation when needed
🔌 Inject and share any service, with no trait or macro required
Agents are exposed to the runtime. Services, in contrast, can be injected and shared without being registered as public operations — keeping your context clean and focused.
Inject<T>#[operation], exposed automaticallyPayloadUse
axor::prelude::*for a complete, developer-friendly import.
[dependencies]
axor = "0.1"
axor-macros = "0.1" # Required for attribute macros
⚠️ You must declare
axor-macrosin yourCargo.toml, but you don't need to import it in your source code — just use the prelude:
use axor::prelude::*;
use std::sync::Arc;
use axor::prelude::*;
trait Logger: Send + Sync {
fn log(&self, message: &str);
}
struct ConsoleLogger;
impl Logger for ConsoleLogger {
fn log(&self, message: &str) {
println!("[LOG] {}", message);
}
}
#[agent]
struct HelloAgent {
logger: Inject<Arc<dyn Logger>>,
}
#[agent_impl]
impl HelloAgent {
#[operation]
fn hello(&self) -> &'static str {
self.logger.resolve().log("Saying hello");
"Hello, world!"
}
}
let mut context = AxorContext::new();
context.register(HelloAgent::default());
context.register_service::<Arc<dyn Logger>>(Arc::new(ConsoleLogger));
context.init();
// Direct call (zero overhead)
let agent = context.resolve::<HelloAgent>();
assert_eq!(agent.hello(), "Hello, world!");
// RPC-style used by web, cli and tauri runtimes
let payload = Payload::new("HelloAgent.hello");
let result = context.invoke(payload);
assert!(result.success);
Introspect all registered agents and operations:
let manifest = context.manifest();
println!("{}", serde_json::to_string_pretty(&manifest).unwrap());
Rust doesn’t provide reflection. You must:
#[agent] to your struct#[agent_impl] to your impl block#[operation] to expose methodsEach operation may take zero or one input, which must:
DeserializeOwnedString, not &str)Return values must be Serialize, but they are optional.
PayloadIn direct mode, everything is statically dispatched and compiled away.
RPC-style invocation uses serde_json::Value, which involves serialization overhead — by design.
Inject<T>axor-web (RPC over HTTP)axor-cli (invoke agents from CLI)axor-tauri (bindings for desktop apps)axor-doc for endpoint documentationMIT © 2025 — Made with ❤️ in Rust