melch

The lifecycle of a request

Melchizedek is a headless Node.js framework built on the Google Agent Development Kit. This walkthrough follows an incoming message from initial file loading through state compilation, tool execution, and long-term memory distillation.

The loader reads the file, the graph compiles per provider, the orchestrator delegates, a tool runs, the ledger records the turn, and memory distils. 1File loading 2Graph compilation 3Orchestrator delegation 4Tool execution 5Telemetry in the ledger 6Memory distillation
  1. File loading

    The loader reads a single syndicate YAML file from your agents directory, confining all paths to that root. It interpolates every binding variable and injects a fresh current_date value on execution. The resulting typed configuration defines the orchestrator, its subagents, assigned model identifiers, tool schemas, instruction blocks, and the active memory mode.

    loadSyndicate('augustin.yaml')
    → { orchestrator, subagents: [XResearcher, WebResearcher], memory_system: 'session-only' }
  2. Graph compilation

    The runtime instantiates an ADK agent for each entry using its designated model identifier. A prefix routing table directs requests to provider adapters, which normalize tool schemas across Gemini, Claude, GPT, Grok, and local models. The framework compiles this execution graph fresh for every request, keeping the HTTP server stateless.

    gemini-*  → native ADK
    claude-*  → lib/models/claudeLlm
    gpt-*     → lib/models/gptLlm
    grok-*    → lib/models/grokLlm
    ollama/*  → lib/models/ollamaLlm   (no key)
  3. Orchestrator delegation

    The orchestrator evaluates incoming messages and calls the subagent whose description fits. The description defines the routing interface while the instruction block determines behavior. A subagent configured without tools reads only what peer agents provide, isolating evaluation logic in designs such as Augustin’s arbiter.

    orchestrator → XResearcher (x_api_search)
                 → WebResearcher (web_search, web_extract)
                 → arbitration, with no tools
  4. Tool execution

    A tool definition specifies a name, description, Zod schema, and execution function. From this single contract, the runtime generates the model-facing function definition and the MCP entry. Schema validation failures return to the model as plain error text rather than process exceptions. Subagents that name an external MCP server discover remote tools dynamically at runtime.

    defineTool({ name, description, schema, execute })
      → toFunctionTool()        // for the model
      → toMcpToolDefinition()   // for MCP clients
  5. Telemetry in the ledger

    When telemetry is enabled, execution records write to three tiers: adk_turns stores one row per turn as the system of record, adk_telemetry records individual spans, and adk_payloads holds sampled full prompts with a thirty-day expiration. External dashboards query these tables, and evaluation suites can grade historical turns to gate automated deployments.

    adk_turns      one row per turn
    adk_telemetry  one row per span
    adk_payloads   sampled prompts, 30-day expiry
  6. Memory distillation

    When a long-term session closes, the pipeline distills conversation transcripts into discrete one-line facts stored in Supabase pgvector. Each record includes a timestamp, source reference, status flag, and associated entities. Incoming corrections mark prior facts superseded. Retrieval combines vector similarity search with in-process re-ranking across entities and dates. Every record remains partitioned by user identifier and subject to deletion.

    fact:   "prefers the 20-day window for the daily read"
    date:   2026-09-12   source: session   status: active
    keys:   [window, daily-read]

Four patterns from the starter pack

Each pattern is one starter-pack file. Choosing a pattern redraws the constellation beside its source file, replays the route a captured run took, and hovering a star lights the lines in the file that declare it.

In this router pattern, RouterAgent reads the request and hands it whole to CodeExpert or MathExpert, running gemini-3.8-flash, then returns that answer. In the captured run, RouterAgent called CodeExpert.

Hover a star to light the lines declaring that agent or tool

config/agents/examples/delegation.yaml
syndicate_name: "Delegation Router Workflow"

variables:
  # Example variables
  domain: "general knowledge"

orchestrator:
  name: "RouterAgent"
  model: "gemini-3.8-flash"
  instruction: |
    You are a triage router. 
    You do NOT answer questions directly if they require specialized knowledge.
    Instead, you examine the user's request and delegate to the appropriate specialist:
    - If the user asks a coding or programming question, delegate to CodeExpert.
    - If the user asks a math or calculation question, delegate to MathExpert.
    - If it's a general greeting or unrelated to those domains, answer it yourself concisely.
  
subagents:
  - name: "CodeExpert"
    model: "gemini-3.8-flash"
    description: "Expert in programming, software development, and debugging."
    instruction: |
      You are an expert programmer. Provide clean, correct, and well-documented code answers.
  
  - name: "MathExpert"
    model: "gemini-3.8-flash"
    description: "Expert in mathematics, formulas, and calculations."
    instruction: |
      You are a math expert. Solve equations and explain the steps clearly.

Long-term memory distils and recalls

Press a session to populate the haze around the Patient Advocate figure; the second session introduces a correction that retires an earlier fact to history without deleting it. Recalling by key lights every record from the engine’s verbatim distillation prompt, history included.

Recall with key
α Asclepiusβ MedScribegoogle_searchpreload_memoryload_memorymetoprolol · dosingcreatinine · kidneymetoprolol · dosingfollow-up · medications
  1. No session has ended yet, so the haze holds nothing.

ActiveHistorical

Surrounding architecture