Releases: cortxai/COREtex
v0.4.5 — COREtex Pipeline System
Overview
This release introduces the COREtex Pipeline System — a configurable, structured execution pipeline that replaces the previously hardcoded classifier → router → worker → executor flow with a modular, registry-backed design.
Building on v0.3.26 Runtime Stabilisation, the platform can now represent pipelines as first-class objects. Pipelines are defined declaratively, registered at startup, and resolved at runtime — making them replaceable without modifying the runtime core.
The default pipeline preserves full backward compatibility: all existing /ingest and OpenWebUI endpoints behave identically to v0.3.26.
✨ Features & Improvements
Pipeline Definition Objects
Two new dataclasses in coretex/runtime/pipeline.py formalise pipeline structure:
PipelineStep— a single step with acomponent_typeandname. Thecomponent_typeis statically typed asLiteral["classifier", "router", "worker", "tool_executor"]and validated at construction time via__post_init__. Invalid types raise a descriptiveValueErrorimmediately.PipelineDefinition— an ordered sequence ofPipelineStepobjects, identified by anameused in observability logs. Provides aget_step(component_type)helper for step lookup.
A make_default_pipeline() factory produces the standard four-step pipeline:
ClassifierBasic → RouterSimple → WorkerLLM → ToolExecutor
This is registered as "default" at startup and is functionally identical to the pre-v0.4.0 hardcoded behaviour.
PipelineRegistry Enhancements
PipelineRegistry is now a fully validated, type-safe registry for PipelineDefinition objects:
register(name, pipeline)— raisesValueError("Pipeline already registered: <name>")on duplicatesget(name)— raisesValueError("Unknown pipeline: <name>")and logsevent=registry_lookup_failedon unknown lookuplist()— enumerates all registered pipeline names- All type signatures use
PipelineDefinitiondirectly (noobjectfallback), enforcing type safety at the registry boundary
PipelineRunner Refactor
PipelineRunner now accepts a pipeline: Optional[PipelineDefinition] argument:
- Component names (
classifier_name,router_name,worker_name) are resolved from the pipeline definition at construction time - If no pipeline is supplied,
make_default_pipeline()is used — preserving pre-v0.4.0 behaviour - All failure handling, latency metrics, and structured log events are fully preserved
Observability: Pipeline Selection Logging
Every request now emits two structured log events at the start of execution, in logical order:
event=request_received request_id=<id>
event=pipeline_selected request_id=<id> pipeline=<name>
This makes the active pipeline fully visible in logs for every request without any additional tooling.
Bootstrap & Distribution Wiring
distributions/cortx/bootstrap.py now creates a PipelineRegistry singleton and registers the default pipeline at startup. main.py retrieves the pipeline definition from the registry and passes it to PipelineRunner, completing the end-to-end pipeline system integration.
Expanded Test Suite
- Test coverage increased from 106 to 129 tests (+23)
- New tests cover:
PipelineStepvalid and invalidcomponent_typevaluesPipelineDefinitionconstruction,get_step(), and empty stepsmake_default_pipeline()name, step count, and step namesPipelineRegistryduplicate registration, unknown lookup,list(), andevent=registry_lookup_failedlogPipelineRunnercomponent name resolution from pipeline definitionPipelineRunnerdefault pipeline fallback whenpipeline=None- Bootstrap default pipeline registration
event=pipeline_selectedlog emission and pipeline name in log- Full async request execution with a custom
PipelineDefinition
- Ollama calls remain fully mocked → deterministic CI/CD testing
🧱 Architecture Update
The execution architecture is unchanged — the pipeline system is a structural layer around the same runtime behaviour:
User (browser)
└─► OpenWebUI (port 3000)
└─► POST /v1/chat/completions
└─► POST /ingest
└─► PipelineRunner.run(ExecutionContext)
│ [pipeline resolved from PipelineRegistry at startup]
├─► ClassifierBasic.classify() → ClassificationResult(intent, confidence)
├─► RouterSimple.route(intent) → handler name
└─► WorkerLLM.generate() → JSON action envelope
│
parse_agent_output → AgentAction
│
ToolExecutor.execute → tool result or direct content
The two-LLM-call invariant, deterministic routing, and strict agent-tool separation are all preserved.
🎯 Design Principles Reinforced
- Everything is replaceable — classifier, router, worker, and tool executor are all resolved by name from registries at runtime; swapping any component requires only a new pipeline registration
- Explicit pipelines — intelligence flows through declared, inspectable
PipelineDefinitionobjects, not opaque frameworks - Single source of truth — the
PipelineRegistryis the authoritative store for all pipeline configurations;main.pyreads from it, not from hardcoded names - Fail-fast validation — invalid step types are rejected at
PipelineStepconstruction, not silently at execution time
⚠️ Current Limitations
No new agent capabilities in this release:
- Single-action responses only
- No memory or conversation history
- No streaming responses
- No multi-agent or planner orchestration
- No persistent storage, authentication, or rate limiting
- Ollama remains the only model backend
- Async tool execution still not supported
- Pipeline steps are resolved at
PipelineRunnerconstruction — runtime pipeline switching is not yet supported
🚧 Next Steps
- Model Provider System — introduce
ModelProviderabstraction; enable hybrid model strategies (Ollama, OpenAI, Anthropic, llama.cpp) - Distribution Layer — first formal CortX distribution (
cortx_local) with fully bootstrapped module loading - Event System — runtime-wide event bus; every action emits structured events for observability and monitoring
- Tool System as Modules — refactor tools into replaceable, user-composable modules
All planned improvements will retain deterministic orchestration and full observability.
🧪 Status
v0.4.5 delivers the COREtex Pipeline System with:
- Declarative
PipelineDefinitionandPipelineStepprimitives - Fully validated
PipelineRegistrywith type-safe signatures PipelineRunnerdriven by pipeline definitions, not hardcoded names- Default pipeline registered at startup, backward compatible with v0.3.26
- Full
event=pipeline_selectedobservability on every request - 129 tests (up from 106), all passing
The platform is now ready for configurable, multi-pipeline workflows on top of the stable deterministic core.
Full Changelog
https://github.com/cortxai/COREtex/commits/feature/v0.4-pipeline-system
v0.3.26 — COREtex Runtime Stabilisation & Hardening
Overview
This release stabilises the COREtex runtime platform and hardens the deterministic tool execution pipeline introduced in previous versions.
Building on v0.3.x Stabilisation, the platform now features full lifecycle logging, registry safety enforcement, and expanded test coverage, ensuring that all modules, tools, and pipelines behave predictably and failures are fully observable.
No new agent capabilities (planners, memory, multi-agent workflows) have been introduced — the focus is robustness, maintainability, and observability.
✨ Features & Improvements
Full Log Lifecycle & Failure Transparency
The PipelineRunner now records all pipeline stages and latency metrics with consistent event names. Explicit failure categories are reinforced:
- Classifier HTTP failure →
event=pipeline_classifier_failure - Worker HTTP failure →
event=pipeline_worker_failure - Agent JSON parse error →
event=pipeline_agent_parse_failure - Tool lookup/runtime error →
event=pipeline_tool_failure
Latency metrics are included in all events for observability.
Registry Validation & Safety
All four registries (Module, Tool, ModelProvider, Pipeline) now enforce:
- Duplicate registration detection →
ValueError("Component already registered: <name>") - Unknown component access →
ValueError("Unknown component: <name>")+event=registry_lookup_failed - Explicit logging on successful and failed lookups
list()andmark_loaded()consistency for all module types
This ensures deterministic behaviour across all modules and tools.
ModuleLoader Hardening
Module loading now validates:
- Module import → logs
event=module_import_failedonImportError - Presence of
register(module_registry, tool_registry, model_registry)function → raisesValueErrorif missing - Signature validation → ensures all three required parameters exist
- Lifecycle events:
event=module_loading_startevent=module_loaded module=<name> registered_components=N- Warnings emitted if no components registered
These changes make module integration safe and predictable.
ExecutionContext Enhancements
ExecutionContext now captures:
metadata: Optional[Dict[str, Any]]for module-specific contextual datatimestamp: floatwall-clock time in addition tot_startmonotonic timestamp
This enables improved observability and traceability of request flows.
ToolExecutor & AgentAction Stability
ToolExecutor.execute()now fully validatesAgentActioninputs- Unknown actions or missing tool names raise structured
ValueErrors - Logs all tool execution steps (
event=tool_execute/event=tool_execute_complete) parse_agent_output()robustly handles malformed JSON, markdown fences, or unexpected fields- Safe fallback: raw output returned to user if parsing fails
Expanded Test Suite
- Test coverage increased to 106 unit + integration tests
- Includes:
- ModuleLoader import/signature/empty-registration tests
- Registry duplicate and unknown lookup tests
- Pipeline failure scenarios
- ToolExecutor dispatch and error handling
- parse_agent_output valid/invalid cases
- Router debug logging
- ExecutionContext timestamp and metadata validation
- Ollama calls remain fully mocked → deterministic CI/CD testing
🧱 Architecture Update
No functional changes to pipeline execution — the current architecture remains:
User (browser)
└─► OpenWebUI (port 3000)
└─► POST /v1/chat/completions
└─► POST /ingest
└─► PipelineRunner.run(ExecutionContext)
├─► ClassifierBasic.classify() → ClassificationResult(intent, confidence)
├─► RouterSimple.route(intent) → handler name
└─► WorkerLLM.generate() → JSON action envelope
│
parse_agent_output → AgentAction
│
ToolExecutor.execute → tool result or direct content
This maintains the two-LLM-call invariant, deterministic routing, and strict agent-tool separation.
🎯 Design Principles Reinforced
- Deterministic Execution — all tools executed only through
ToolExecutor - Separation of Concerns — agents decide actions; system executes
- Explicit Capabilities — all tools registered at startup
- Robust Failure Handling — pipeline resilient to HTTP errors, invalid JSON, unknown tools
⚠️ Current Limitations
No major new capabilities:
- Single-action responses only
- No memory or conversation history
- No streaming responses
- No multi-agent or planner orchestration
- No persistent storage, authentication, or rate limiting
- Ollama remains the only model backend
- Async tool execution still not supported
🚧 Next Steps
- Tool Ecosystem Expansion — HTTP, database, shell, vector search, structured data
- Planner & Task Graphs — deterministic multi-step execution graphs
- Multi-Agent Workflows — orchestrated task pipelines
- Persistent Memory — optional local-first memory layer
All planned improvements will retain deterministic orchestration and observability.
🧪 Status
v0.3.26 stabilises the COREtex runtime with:
- Hardened module loading and registry safety
- Full structured logging of pipelines, tools, and agent outputs
- Robust AgentAction parsing and safe fallbacks
- Expanded test coverage (106 tests)
- Clear separation between runtime, modules, and distributions
The platform is now fully ready for building advanced agent workflows on top of a stable deterministic core.
Full Changelog
v0.2.0 — Deterministic Tool Execution Layer
Overview
This release introduces the first deterministic tool execution layer for CortX.
Building on the orchestration foundation established in v0.1.0, the platform can now execute structured actions requested by the worker agent while maintaining the core design goals of transparency, determinism, and local-first operation.
The worker agent now returns a structured JSON action envelope rather than raw text. This output is parsed and executed by a centralised ToolExecutor, ensuring that agents never directly execute tools and that all actions remain observable and controllable.
This phase validates the architecture required for safe agent-tool interaction without introducing autonomous loops or complex planning behaviour.
✨ Features
Deterministic Tool Execution Layer
Agents can now request external actions through a structured JSON interface.
Example agent output:
{
"action": "tool",
"tool": "read_file",
"args": {
"path": "README.md"
}
}The action envelope is parsed and executed by the ToolExecutor, which determines
whether to:
- return direct content to the user
- execute a registered tool
- reject invalid actions
This preserves strict separation between agent reasoning and system execution.
Tool Registry
All available tools are registered in a central ToolRegistry at application startup.
Benefits:
- deterministic tool lookup
- prevention of duplicate tool registration
- explicit declaration of system capabilities
New tools can be added by implementing a tool module and registering it in bootstrap_tools.py.
Filesystem Tool (Initial Capability)
The first tool implementation provides read-only filesystem access.
Tool: read_file
Arguments:
path— path to the file to read
Example action:
{
"action": "tool",
"tool": "read_file",
"args": {
"path": "notes.txt"
}
}The tool returns the text content of the file or a safe error message if the file does not exist.
This provides a simple but practical demonstration of agent-driven tool usage.
Structured Agent Output
Worker agents now return structured JSON responses rather than free-form text.
Supported actions:
{"action": "respond", "content": "text to return to the user"}or
{"action": "tool", "tool": "<tool_name>", "args": {...}}This structure enables deterministic parsing and execution while keeping the worker model responsible only for deciding what action to request.
Safe Action Parsing
Agent output is parsed through a dedicated parse_agent_output function that:
- strips markdown fences
- parses JSON safely
- validates structure through the
AgentActionmodel - logs parsing failures
If parsing fails, the system gracefully falls back to treating the raw output as direct user content.
This ensures the system remains robust to imperfect LLM output.
Tool Execution Logging
Tool execution is fully observable through structured logs.
Example events:
event=agent_output_received
event=tool_execute tool=read_file
event=tool_execute_complete tool=read_file
If a tool lookup fails or execution errors occur, these are logged explicitly, allowing developers to trace the entire execution path.
Expanded Test Coverage
The test suite has been expanded to include comprehensive coverage of the tool execution layer.
New tests validate:
- tool registration
- duplicate tool detection
- tool lookup failures
- agent action parsing
- executor dispatch logic
- graceful fallback behaviour
All Ollama calls remain fully mocked to ensure deterministic tests.
🧱 Updated Architecture
The request pipeline now includes a deterministic tool execution step.
User (browser)
└► OpenWebUI (port 3000)
└► POST /v1/chat/completions
└► POST /ingest
├► Classifier — LLM call 1/2 → intent + confidence
├► Router — pure Python dict lookup → handler
└► Worker — LLM call 2/2 → JSON action envelope
│
parse_agent_output
│
ToolExecutor.execute
│
Tool result or direct response
This architecture preserves the original two-LLM-call invariant while allowing agents to safely request external capabilities.
🎯 Design Principles Reinforced
Deterministic Execution
Tools are executed exclusively through the ToolExecutor, ensuring predictable and auditable behaviour.
Strict Separation of Concerns
Agents decide what action to request, while the system decides how to execute it.
Explicit Capabilities
All available tools are registered at startup rather than discovered dynamically.
Robust Failure Handling
Invalid JSON, unknown tools, or worker failures are handled gracefully without crashing the orchestration pipeline.
⚠️ Current Limitations
This release intentionally avoids more advanced agent capabilities while validating the tool execution architecture.
Still not implemented:
- multi-step tool chaining
- planner-driven tool workflows
- multi-agent collaboration
- memory or conversation history
- streaming responses
- persistent storage
- authentication or rate limiting
- multiple model providers
Tool execution currently supports single-action responses only.
🚧 Next Steps
The next development phases will focus on expanding agent capabilities while maintaining deterministic orchestration.
Planned areas of exploration include:
- Tool Ecosystem Expansion
- Additional tools such as:
- HTTP API access
- database queries
- vector search
- shell command execution
- structured data processing
Planner and Task Graphs
Introducing a deterministic planning layer capable of constructing multi-step execution graphs.
Multi-Agent Workflows
Enabling specialised agents to collaborate through orchestrated task pipelines.
Persistent Memory
Adding optional memory layers while preserving the platform's local-first design.
🧪 Status
This release represents the first operational integration of agent-driven tool execution within the CortX architecture.
The platform now supports:
- deterministic intent routing
- structured agent responses
- safe tool invocation
- observable execution paths
The system remains intentionally minimal but now establishes the foundation required for building complex agent workflows on top of a deterministic core.
Full Changelog:
PoC
v0.1.0 — Local-First Agent Orchestration PoC
Overview
This release introduces the first working Proof of Concept for a local-first AI orchestration platform.
The system focuses on clarity, determinism, and debuggability, avoiding opaque “agent frameworks” and instead implementing a simple, inspectable architecture that can serve as a solid foundation for future expansion.
This release establishes the core architecture required to build a reliable agent system before introducing more complex features such as tool execution, memory, or multi-agent orchestration.
✨ Features
Local-First Architecture
The system is designed to run entirely locally, avoiding reliance on cloud services or proprietary platforms.
Key benefits:
- No external orchestration services
- Works offline
- Full control over infrastructure
- Easy to self-host
Deterministic Intent Routing
User requests are routed through a deterministic intent router rather than relying on emergent LLM behaviour.
This ensures:
- predictable routing
- transparent debugging
- consistent agent selection
Example log line:
event=intent_router request_id=<id> intent=analysis route=worker confidence=0.90 input="Compare Kubernetes and Nomad"
Agent Separation of Concerns
Agents are implemented as focused components responsible for a single domain.
Intent categories:
execution— direct task completion (write, generate, create, summarise)planning— step-by-step breakdown (how to build, launch, implement)analysis— open-ended thinking (compare, evaluate, design)
Each intent routes to the same worker with a different prompt template, keeping
response style consistent with what the user asked for.
This avoids the “do-everything agent” anti-pattern common in early agent frameworks.
OpenWebUI as a Thin UI Layer
The UI layer is provided by OpenWebUI, used strictly as a frontend interface.
The orchestration system runs independently and communicates through an API layer.
Benefits:
- clean separation of UI and orchestration
- UI can be replaced without changing backend logic
- orchestration remains framework-agnostic
Transparent Logging
The system emits structured logs for key orchestration steps, enabling full traceability.
Example execution trace:
event=request_received request_id=<id>
event=classifier_result request_id=<id> intent=analysis confidence=0.90 source=llm
event=intent_router request_id=<id> intent=analysis route=worker confidence=0.90
event=worker_start request_id=<id> worker=worker intent=analysis
event=worker_complete request_id=<id> worker=worker latency_ms=3240
event=request_complete request_id=<id> intent=analysis total_latency_ms=5063
This allows developers to understand exactly how a request moved through the system.
🧱 Architecture
Current request flow:
User (browser)
└► OpenWebUI (port 3000)
└► POST /v1/chat/completions (Ingress API, port 8000)
└► POST /ingest
├► Classifier — LLM call 1/2 → intent + confidence
├► Router — pure Python dict lookup → handler
└► Worker — LLM call 2/2 → response text
The architecture deliberately avoids:
- hidden agent loops
- automatic tool execution
- black-box memory systems
- implicit orchestration
Every step in the pipeline is explicit and inspectable.
🎯 Design Principles
This project prioritises:
Determinism
Agent behaviour should be predictable and observable.
Local Control
The platform should run entirely on local infrastructure.
Transparency
System behaviour should be visible through logs and simple architecture.
Incremental Complexity
Capabilities will be added gradually rather than introducing large frameworks.
⚠️ Current Limitations
This release intentionally excludes several features that will be introduced in later phases:
- tool execution
- async task execution
- multi-agent collaboration
- long-term memory
- distributed task orchestration
- cloud brokers
The focus of this phase was validating the core orchestration architecture.
🚧 Next Steps
The next development phase will introduce a deterministic Tool Execution Layer, enabling agents to request actions such as:
- filesystem access
- API calls
- database queries
- vector search
- shell commands
This will be implemented using a centralised executor and tool registry, ensuring safe and observable tool usage.
Future phases will explore:
- task graphs and planners
- multi-agent workflows
- async execution
- persistent memory systems
🧪 Status
This release represents a stable architectural PoC, suitable for experimentation and further development.
The system is intentionally minimal but establishes the foundations required to build a a robust agent platform.
Full Changelog: https://github.com/philbudden/cortex/commits/v0.1.0