Skip to main content

System Architecture

Console V2 (internally named Weave) was engineered as a multi-tenant B2B platform for building and running business processes composed of versioned steps, skills, tools, and human approvals.

In this architecture, the primary unit of work is the Process—a versioned graph of steps executing as a ProcessRun. Processes serve as the core domain entity, while agents, modular skills, and tools represent capabilities invoked by individual process steps.

┌────────────────────────────────────────────────────────────────────────┐
│ THE PROCESS DOMAIN │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ Process (UUID) ──► ProcessVersion (Immutable) │ │
│ │ │ │ │
│ │ ▼ (Graph of 20 Step Types) │ │
│ │ [ProcessStep ──► ProcessStep ──► ProcessStep] │ │
│ └──────────────────────────────┬───────────────────────────────────┘ │
│ │ Trigger (Webhook / Schedule / Event) │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ ProcessRun (State Machine: running ──► waiting/paused ──► done) │ │
│ │ ├── StepRun (Per-step execution records & audit trail) │ │
│ │ ├── ExecutionContext (Scoped runtime variables & payloads) │ │
│ │ └── ExecutionUsage (Metered compute & token accounting) │ │
│ └──────────────────────────────┬───────────────────────────────────┘ │
└─────────────────────────────────┼──────────────────────────────────────┘
▼
┌────────────────────────────────────────────────────────────────────────┐
│ EXECUTION RUNTIME (agentictools/runtime/) │
│ ExecutionRuntime │ Planner (DAG Generation) │ ToolRunner │
│ SafetyLayer │ PolicyEngine │ ModelRouter (LLM) │
│ SessionManager │ WorkspaceManager │ ExternalAdapters │
└────────┬────────────────────────┬───────────────────────────────┬──────┘
│ Tool Invocation │ Skill Execution │ Memory Query
┌────────▼──────────────┐ ┌──────▼────────────────┐ ┌───────────▼──────┐
│ TOOL BUS │ │ SKILL REGISTRY │ │ BRAINBOX MEMORY │
│ 29 registered tools │ │ ~95 domain skills │ │ 4-layer substrate│
│ BaseTool schemas │ │ Finance, Governance, │ │ 384-dim pgvector │
│ MEDIA_ROOT sandbox │ │ Risk, Maintenance │ │ Pluggable provider│
└───────────────────────┘ └───────────────────────┘ └──────────────────┘

1. The Process Domain​

The process domain models the entire business workflow as an auditable, version-controlled graph:

Domain Entities​

ModelPurpose
ProcessA tenant-scoped business process (UUID primary key; states: draft, active, archived).
ProcessVersionAn immutable-on-publish version, auto-numbered per process to ensure reproducibility.
ProcessStepOne node in a version's graph, supporting 20 distinct step types.
TriggerExternal entry point (unauthenticated webhook ingress, cron schedule, or internal event).
ProcessRunAn execution instance of a published version governed by a validated state machine.
StepRunExecution record for a single step within a run, storing input payloads, outputs, and execution duration.
ExecutionContextDynamic variable store for a run (e.g., inbound webhook JSON, intermediate step variables).
OutcomeTerminal result recorded upon completion or failure of a process run.
ExecutionUsageMetered usage tracking compute duration and LLM tokens consumed for tenant billing.

The 20 Step Types​

Process graphs are constructed from 20 modular step primitives:

[Entry & Ingress] event, schedule, webhook, manual
[Capabilities] skill, tool, agent
[Human Oversight] human_task, approval, escalate
[Control Flow] condition, branch, loop, parallel, join, subprocess
[Time & Control] wait, timer, notify, complete

ProcessRun State Machine​

A ProcessRun transitions through strictly validated model states:

draft ──► running ──┬──► waiting (awaiting external trigger or async tool)
├──► paused (suspended for human approval or policy gate)
│
└──► [Terminal]: completed | failed | cancelled

2. Core Execution Runtime (agentictools/runtime/)​

The execution runtime orchestrates the step lifecycle, context resolution, and external model interactions:

  • ExecutionRuntime: Core engine driving a ProcessRun across its step dependencies.
  • Planner / TaskPlan: Evaluates step prerequisites, builds the execution DAG, and schedules parallel branches.
  • ToolRunner: Resolves tool implementations, checks permissions, and executes sandboxed tool operations.
  • SafetyLayer & PolicyEngine: Validates actions against enterprise policy rules prior to dispatch.
  • ModelRouter: Routes LLM prompts across multiple model providers with automatic failover and token accounting.
  • WorkspaceManager: Enforces per-run file isolation. Tools writing generated files utilize BaseTool.resolve_file_path(), which strictly sandboxes all output under MEDIA_ROOT/generated/.
  • MemoryBus + MemoryProvider: Pluggable memory interface decoupling memory retrieval from external storage substrates.

3. Tool Bus & Skill Registry​

Console V2 replaced persona-based tool coupling with centralized capability registries.

The Tool Bus (29 Registered Tools)​

All tools inherit from BaseTool and are auto-discovered at startup via AgentictoolsConfig.ready(). Each tool is registered using a declarative decorator:

@ToolRegistry.register(
name="query_postgresql",
description="Executes a sanitized read-only query against configured databases.",
permissions=["db:read"],
parameters={
"type": "object",
"properties": {
"query": {"type": "string"},
"database_alias": {"type": "string"}
},
"required": ["query"]
},
risk_level="MEDIUM"
)
class PostgreSQLTool(BaseTool):
def execute(self, context, **kwargs):
# Sandboxed execution logic
...

The Skill Registry (~95 Modular Skills)​

Skills are higher-order capabilities grouped by domain. Rather than running separate vertical agent daemons, capabilities from retired legacy agents were converted into reusable skills:

  • Finance & Accounting: Invoice extraction, ledger reconciliation, tax calculations.
  • Governance & Compliance: Vendor verification, audit trail checks, GDPR data scrubbing.
  • Maintenance & DevOps: Dependency scanning, database index health checks.
  • Risk Detection: Fraud pattern analysis, AML compliance scoring.

4. BrainBox: 4-Layer Memory Substrate​

The brainbox/ module provides an optional multi-layer memory substrate:

  1. Event Store: Chronological stream of all system events and user actions.
  2. Semantic Memory: Document chunks indexed into PostgreSQL with pgvector using 384-dimensional dense embeddings.
  3. Knowledge Graph: Entity-relationship nodes mapping organizations, accounts, and cross-system entities.
  4. Inference Layer: Synthesizes facts and past run histories to augment prompt contexts.

Resilience Invariant: Nothing above the memory provider boundary imports BrainBox directly. The runtime interacts strictly through a MemoryProvider interface. If BrainBox is unreachable or unprovisioned, process runs continue operating without disruption.


5. Governance & Human Approval Queue​

Governance is integrated directly into the process graph via dedicated step types (approval, escalate, human_task) and runtime policies:

  • ApprovalQueue: Supports three organizational autonomy modes:
    • Manual: All capability steps require human sign-off.
    • Hybrid: Routine steps proceed automatically; steps with high risk_level or explicit approval nodes suspend into the queue.
    • Autonomous: Full end-to-end execution constrained by hard policy ceilings.
  • PolicyRuleModel: Evaluates glob-matched action rules (e.g., financial:payout:*), parameter thresholds (e.g., amount <= 5000), and hourly rate limits.

6. Authentication & Fail-Closed Multi-Tenancy​

Console V2 enforced strict cryptographic isolation across all operations:

Authentication Pipeline​

APIKeyOrJWTAuthentication validates JWKS-signed JSON Web Tokens from the central identity provider, falling back to local SimpleJWT, and finally workspace API keys. Authenticators return lightweight principal objects (JWTUser, APIKeyUser, ServiceUser, MonicaUser) rather than full model instances.

Fail-Closed Tenant Cascade​

Tenant context is resolved strictly on the server side and is never accepted from client-supplied request payloads:

tenant = (
getattr(request, 'tenant', None)
or getattr(request.user, 'tenant', None)
or getattr(getattr(request.user, 'profile', None), 'tenant', None)
)
if not tenant:
return MyModel.objects.none() # Fail-closed: NEVER return .all()

7. Monica Omnichannel Support Surface​

While all other vertical agents were retired, Monica survived as a dedicated, live customer-facing support surface (monica/ app):

  • Capabilities: Customer FAQ RAG, dispute intake, appointment scheduling.
  • Public Chat Widget: Embeddable on external websites, authenticated via monica_public_key and strictly locked to an origin allow-list.

Next Steps in Archive​