Overview

Noetic is a TypeScript agent framework built on seven composable primitives.

Philosophy

Most frameworks give you a pre-built agent to tweak. Noetic gives you the primitives to build agents from scratch -- or grab a batteries-included pattern to start fast.

Every agent is a composition of small, typed building blocks. There is no hidden control flow, no magic base class, and no runtime surprises. You describe what your agent does; the interpreter figures out how to run it.

The Seven Primitives

Noetic's entire execution model is built from seven primitives. Each one is a Step -- a typed, serializable unit of work.

PrimitiveKindPurpose
step.runrunExecute arbitrary async code
step.llmllmCall a language model
step.tooltoolInvoke a single tool directly
branchbranchConditional routing -- pick one step or skip
forkforkParallel execution -- race, all, or settle
spawnspawnIsolated child execution with context strategies
looploopRepeat a step until a predicate says stop

How They Compose

Primitives nest freely. A loop body can be an llm step, a branch, or even another loop. A fork can fan out into spawned sub-agents. The type system keeps inputs and outputs aligned at every boundary.

import { branch, fork, spawn, step, until } from '@noetic/core';

// A branch that picks between two LLM steps
const router = branch({
  id: 'pick-model',
  route: (input, ctx) => {
    if (input.includes('code')) {
      return step.llm({
        id: 'code-llm',
        model: 'gpt-4o',
      });
    }
    return step.llm({
      id: 'chat-llm',
      model: 'gpt-4o-mini',
    });
  },
});

Beyond Primitives

Memory System

Noetic ships with a layered memory system -- working memory, observational memory, and durable task state. Memory layers participate in spawn/return lifecycles and project context into LLM-friendly views.

Patterns

Pre-composed agent patterns like react and adaptivePlan give you production-ready agents in a single function call. They are built entirely from the same primitives you use directly.

Runtime

The InMemoryRuntime orchestrates execution, manages context, and wires up observability. Swap in your own Runtime implementation for persistence, queuing, or distributed execution.

Next Steps

On this page