| name | agentfootprint |
| description | Use when building AI agents with agentfootprint โ LLMCall, Agent, RAG, FlowChart, Swarm concepts, mock/anthropic/openai adapters, tools, recorders, compositions, and streaming. Also use when someone asks how agentfootprint works or wants to understand the framework. |
agentfootprint โ The Explainable Agent Framework
agentfootprint structures AI agents as composable flowcharts with adapter-swap testing. Every concept uses LLMProvider โ swap mock([...]) for createProvider(anthropic(...)) with zero code changes.
Core principles:
- Adapter-swap testing ($0 test runs, deterministic assertions)
- Concept ladder: LLMCall < RAG < Agent < FlowChart < Swarm
- Built-in recorders for tokens, cost, tool usage, quality, guardrails
- Collect during traversal (inherited from footprintjs)
npm install agentfootprint
Five Concepts (Builder API)
LLMCall โ Single LLM call, no tools
import { LLMCall, mock } from 'agentfootprint';
const caller = LLMCall.create({ provider: mock([{ content: 'Hello!' }]) })
.system('You are helpful.')
.recorder(tokens)
.build();
const result = await caller.run('Hi');
Agent โ Full ReAct agent with tools
import { Agent, defineTool, mock } from 'agentfootprint';
const agent = Agent.create({ provider: mock([...]), name: 'my-agent' })
.system('You are a research assistant.')
.tool(searchTool)
.maxIterations(5)
.recorder(tokens)
.build();
const result = await agent.run('Find info about AI');
RAG โ Retrieve-Augment-Generate
import { RAG, mock, mockRetriever } from 'agentfootprint';
const rag = RAG.create({
provider: mock([{ content: 'Answer.' }]),
retriever: mockRetriever([{ chunks: [{ content: 'doc', score: 0.9 }] }]),
})
.system('Answer using context.')
.topK(5)
.build();
FlowChart โ Sequential multi-agent composition
import { FlowChart } from 'agentfootprint';
const pipeline = FlowChart.create()
.agent('researcher', 'Research', researchRunner)
.agent('writer', 'Write', writerRunner)
.build();
Swarm โ LLM-routed multi-agent handoff
import { Swarm, createProvider, anthropic } from 'agentfootprint';
const swarm = Swarm.create({ provider: createProvider(anthropic('claude-sonnet-4-20250514')) })
.system('Route to specialists.')
.specialist('research', 'Research.', researchRunner)
.specialist('write', 'Write.', writerRunner)
.build();
Provider System
- LLMProvider โ
mock([...]), createProvider(anthropic(...)), createProvider(openai(...))
- PromptProvider โ
staticPrompt(), templatePrompt(), skillBasedPrompt(), compositePrompt()
- MessageStrategy โ
fullHistory(), slidingWindow(), charBudget()
- ToolProvider โ
staticTools(), dynamicTools(), agentAsTool()
Tools
import { defineTool } from 'agentfootprint';
const tool = defineTool({
id: 'calculator',
description: 'Perform arithmetic',
inputSchema: { type: 'object', properties: { expression: { type: 'string' } } },
handler: async (input) => ({ content: String(eval(input.expression)) }),
});
Recorders
import { TokenRecorder, CostRecorder, TurnRecorder, ToolUsageRecorder } from 'agentfootprint';
const tokens = new TokenRecorder();
agent.recorder(tokens);
await agent.run('Hello');
tokens.getStats();
Compositions (Resilience)
import { withRetry, withFallback, withCircuitBreaker } from 'agentfootprint';
const resilient = withRetry(provider, { maxRetries: 3 });
const fallback = withFallback([primaryProvider, backupProvider]);
Anti-Patterns
- Never use functional API โ always use
.create({...}) builder pattern
- Never pass recorders via constructor โ use
.recorder() builder method
- Don't use
name/parameters on defineTool โ use id/inputSchema
- Don't post-process execution โ use recorders
Build & Test
npm run build
npm test