Core Primitives
The seven object-safe traits — Model, Tool<Ctx>, Session, Guardrail<Ctx>, Hook<Ctx>, Agent<Ctx>, Runner<Ctx> — and the concrete carrier types they share. The trait surface lives in the paigasus-helikon-core crate, the dependency root every other crate builds on.
These seven were chosen as the minimum viable surface. Other primitives users may expect — Memory, KnowledgeBase, Toolset, Plugin — are either compositions of these seven (a "toolset" is just a function returning Vec<Arc<dyn Tool<Ctx>>>) or premature.
The seven traits
Each is object-safe by design, so applications hold heterogeneous registries behind Arc<dyn _>.
Model— the single canonical async interface to an LLM provider.async fn invoke(&self, request: ModelRequest, cancel: CancellationToken)returns aBoxStreamofModelEvents. Capability differences (streaming, tools, structured output, vision, …) are surfaced throughModelCapabilitiesrather than split into separate traits. One trait covers OpenAI Chat Completions, OpenAI Responses, Anthropic Messages, Bedrock Converse, and Gemini.Tool<Ctx>— a callable an agent can invoke. Reportsname(),description(), a JSONschema(), and aneffect()(ToolEffect::ReadOnly/Write/SideEffect, used by the permission layer).async fn invoke(&self, ctx: &ToolContext<Ctx>, args: Value)returns aToolOutput.Session— conversation persistence as an append-only event log, not a flat message list. Three methods:append,events(optionallysinceaSequenceId), andsnapshot(aConversationSnapshotprojection of the log). The event-log shape buys deterministic replay for evals, event-sourced durability, and an audit trail.Guardrail<Ctx>— an input/output safety check that runs in parallel with the agent.async fn checkreturns aGuardrailVerdict(PassorTripwire); a tripwire halts the run.Hook<Ctx>— a lifecycle interceptor.async fn on_event(&self, ctx, event: &HookEvent)returns aHookDecision(Allow,Deny,ReplaceInput,ReplaceOutput,InjectSystemMessage). Hooks are observation and side effects — distinct from permissions (authorization) and guardrails (content).Agent<Ctx>— one trait for both LLM-driven and workflow agents. Reportsname()/description();async fn run(&self, ctx: RunContext<Ctx>, input: AgentInput)returns aBoxStream<'static, AgentEvent>.Runner<Ctx>— the pluggable execution backend (the durability seam).run/run_streameddrive an agent to aRunResult/RunResultStreaming, withresume/resume_streameddefaulting on top. Object-safe: methods take&dyn Agent<Ctx>.
Auxiliary traits
Beyond the seven, core ships a few narrower traits that support them:
PermissionPolicy<Ctx>— acanUseTool-style authorizer returning aPermissionDecision(Allow/Deny/AskUser/Replace). Sits behind thePermissionModeenum and first-classDenyRules.ApprovalHandler— resolves aPermissionDecision::AskUserinto anApprovalOutcome. Non-generic (it needs noCtx).Instructions<Ctx>— renders the system prompt for a turn. Implemented forString,&'static str, and anyFn(&RunContext<Ctx>) -> String, so an agent's instructions can be static text or dynamic per-run.
Concrete carrier and implementation types
The traits ship with concrete types that carry data across their boundaries and a handful of ready-to-use implementations:
LlmAgent<Ctx, M, T>and its typestate builder — the LLM-drivenAgent. Construct viaLlmAgent::builder::<Ctx>(), then.name(...),.model(...),.instructions(...),.tools(...),.handoffs(...),.output_type::<T>(), and.build().MemorySession— an in-memorySessionbacked by aMutex<Vec<SessionEvent>>, for tests and ephemeral runs. (For persistent storage, seepaigasus-helikon-sessions-sqlite.)- Workflow agents —
SequentialAgent(compose with.then(...)/.then_keyed(...)),ParallelAgent, andLoopAgent, each implementingAgent<Ctx>so they nest like any other agent. RunContext<Ctx>— the per-run state shared across loop, tools, guardrails, and hooks (user context,Sessionhandle,HookRegistry,TracerHandle,CancellationToken). Build withRunContext::new(user_ctx, session, hooks, tracer, cancel)(all five arguments explicit) or useRunContext::ephemeral(user_ctx)as the shorthand for the all-defaults case (in-memory session, empty hooks, default tracer, fresh cancel token); individual parts can then be overridden with the consuming setters.with_session(...),.with_hooks(...),.with_tracer(...),.with_cancel(...).RunConfigcarries per-run knobs (max_turns,timeout,parallel_tool_call_limit,max_agent_depth).RunResult<T>(and its streaming counterpartRunResultStreaming) aggregate the run'sfinal_output,events, andTokenUsage.- Event and item carriers —
AgentEventis the unified stream variant emitted by everyAgent(lifecycle, rawTokenDelta/ReasoningDelta/ToolCallDelta, semanticMessageOutput/ToolCallItem/ToolOutputItem,HandoffItem, control signals, and terminalRunCompleted/RunFailed).Item/ContentPartare the conversation-message carriers;ModelEvent,ModelRequest, andToolDefcross the model boundary;SessionEventis the log entry aSessionpersists.
Canonical reference
The workspace is published on crates.io, and rustdoc HTML is live on docs.rs at https://docs.rs/paigasus-helikon-core. Each trait carries a worked rustdoc example; the published rustdoc is the canonical reference for exact signatures and carrier-type fields.