Getting Started
Install Noetic and build your first agent in under 5 minutes.
Installation
npm i @noetic-tools/coreOr with your preferred package manager:
bun add @noetic-tools/core
pnpm add @noetic-tools/core@noetic-tools/core pulls in @openrouter/agent and zod automatically. It runs on Node.js 18+ and Bun.
Set Your API Key
Noetic calls LLMs through OpenRouter. Create a key at openrouter.ai/keys and export it — the runtime reads OPENROUTER_API_KEY by default:
export OPENROUTER_API_KEY=sk-or-...Your First Agent
Build a ReAct agent that loops over a callModel step, calling tools until the model has its answer. Here is the whole program — save it as agent.mjs and run node agent.mjs:
import { AgentHarness, any, callModel, loop, until } from '@noetic-tools/core';
import type { ContextData } from '@noetic-tools/core';
import { z } from 'zod';
// A tool the agent can call. Inputs and outputs are validated with zod.
const searchTool = {
name: 'search',
description: 'Search the web for information',
input: z.object({ query: z.string() }),
output: z.object({ result: z.string() }),
execute: async (args: { query: string }) => {
return { result: `Results for: ${args.query}` };
},
};
// A model call, looped until the model stops calling tools. The generics name
// the context shape and the step's input/output types the harness expects.
const assistant = callModel<ContextData, string, string>({
id: 'assistant',
model: 'openai/gpt-4o', // OpenRouter model id (provider/model)
instructions: 'You are a helpful research assistant.',
tools: [searchTool],
});
const agent = loop({
id: 'agent-loop',
steps: [assistant],
until: any(until.noToolCalls(), until.maxSteps(5)),
});
// The harness runs the agent. `name` and `params` are required;
// `callModelDefaults` selects the provider and reads OPENROUTER_API_KEY from the env.
const harness = new AgentHarness({
name: 'researcher',
agentGraph: agent,
params: {},
callModelDefaults: { provider: 'openrouter' },
});
await harness.execute('What are the latest developments in AI?');
const response = await harness.getAgentResponse();
console.log(response.text);Run it and the model's final answer prints to your terminal.
Using TypeScript? Save the file as
agent.tsand run it withbunx tsx agent.ts(orbun run agent.ts) — both execute TypeScript directly, no build step. Plainnoderuns the.mjsversion above.
What Happens When You Run It
- The LLM receives the system prompt and your input.
- If the model calls a tool, Noetic executes it and feeds the result back.
- The loop repeats until the model responds without tool calls, or
maxStepsis reached. getAgentResponse()resolves with the finalresponse.text.
Model ids use OpenRouter's
provider/modelformat (e.g.openai/gpt-4o,anthropic/claude-sonnet-4). Browse them at openrouter.ai/models.
That is the whole ReAct shape expressed in three primitives: callModel, until.noToolCalls, and a loop. Everything else in Noetic composes the same way -- see Loop & Until.
Next Steps
- Overview -- understand Noetic's philosophy and the 8 primitives.
- Steps -- learn about
runCode,callModel, andinvokeTool. - AgentHarness -- the runtime that executes agents.
- Control Flow --
conditionalandinParallelfor routing and parallel logic. - Loop & Until -- iteration with termination predicates.