The Layer-Capability Pattern is an architectural approach designed for building Extended Intelligence systems that prioritize simplicity, flexibility, and scalability. It is particularly effective for interactive systems, where user inputs require intelligent and contextually relevant responses.
While Large Language Models (LLMs) are powerful, their inherently probabilistic nature introduces significant limitations. The Layer-Capability Pattern addresses these limitations by structuring interactions within the system, enabling more reliable and intelligent outcomes than any individual component could achieve alone.
At the core of the Layer-Capability Pattern is the Cortex trait, which defines a unified, asynchronous, message-based architecture for handling incoming requests:
#[async_trait]
pub trait Cortex {
async fn tell(&self, req: RequestMessage) -> Result<(), anyhow::Error>;
}This trait ensures that all components—whether layers or capabilities—handle incoming messages uniformly.
The Layer trait expands upon the Cortex trait, introducing a method specifically for processing outgoing response messages:
#[async_trait]
pub trait Layer: Cortex {
async fn respond(&self, res: ResponseMessage) -> Result<ResponseMessage, anyhow::Error>;
}This allows layers to independently manage response transformations, validations, or even rejections.
The Layer-Capability Pattern workflow:
- A user submits a message via an interface or REPL.
- The message is transformed into a structured
RequestMessage. - This request sequentially passes through multiple layers, each capable of modifying or rejecting it.
- The final layer, known as the Capability Selector, evaluates registered capabilities to determine the best fit.
- The chosen capability processes the request and returns a structured
ResponseMessage. - The response travels back through the layers, undergoing optional processing via each layer’s
respondmethod, before reaching the user.
sequenceDiagram
actor U as User
participant I as Interface
participant M as Main
participant H as Handler
participant L as Layers
participant CSL as Capability Selector Layer
participant C as Capability
U ->> I: Message
I ->> M: RequestMessage
M ->> H: RequestMessage
H ->> L: RequestMessage
L ->> CSL: RequestMessage
CSL ->> C: RequestMessage
C ->> CSL: ResponseMessage
CSL ->> L: ResponseMessage
L ->> H: ResponseMessage
H ->> M: ResponseMessage
M ->> I: ResponseMessage
graph LR
M[Main] -- RequestMessage --> H[Handler]
H --> L["Layers(n)"]
L --> CSL[Capability Selector Layer]
CSL -- "check()"--> C[Capability]
CSL -- "check()" --> C2[Selected Capability]
CSL -- "check()" --> C3[Capability]
CSL -- "execute()" --> C2
C2 --> CSL
CSL --> L
L --> H
H -- ResponseMessage --> M
All interactions follow a consistent Request-Response format:
- Components receive a
RequestMessageand return aResponseMessage.
Capabilities self-register within a central registry, providing descriptive metadata and logic to aid in dynamic selection.
Layers sequentially process requests and responses, potentially enabling:
- Security enforcement
- Contextual enrichment
- Message transformation
- Response validation and filtering
Capabilities dynamically assess their suitability for handling requests via scoring:
- Simple capabilities may rely on exact-match scoring.
- Complex capabilities may utilize ML-driven scoring.
#[async_trait]
pub trait Capability: Cortex {
async fn check(&self, message: &RequestMessage) -> Result<f32, anyhow::Error>;
async fn tell(&self, message: RequestMessage) -> Result<(), anyhow::Error>;
}The Layer-Capability Pattern includes advanced functionalities to enhance robustness and flexibility:
Capability selection operates in two stages:
-
Score-based Selection:
- Capabilities provide suitability scores (1.0: perfect, -1.0: unsuitable).
- Capabilities with high scores (>0.5) are immediately selected.
-
AI-based Selection (Fallback):
- In absence of a high-scoring match, an LLM selects capabilities based on their descriptions.
This architecture facilitates:
- Bidirectional Communication: Layers and capabilities communicate responses independently.
- Asynchronous Operations: Components process requests without sequential waiting.
- Event-Driven Interactions: Components react dynamically to events and internal logic.
- Flexible Routing: Adaptive and context-aware message routing.
These attributes enable sophisticated interaction patterns:
- Streaming responses
- Concurrent request processing
- Proactive notifications
- Multi-response interactions
The Layer-Capability Pattern provides a robust and flexible framework for developing intelligent systems. By integrating structured logic with probabilistic language models, it significantly enhances interaction quality and system scalability.