Build reliable AI agents.
f(x) is a functional agent framework where every step is a pure function Context → Context. This makes your agents predictable, testable, and debuggable.
Context = a Value, Steps = Transformations
f(x) treats context as an explicit state value where every step is a pure function Context → Context. This makes context testable and replayable - you can diff context before/after each step, assert contracts, and audit the exact payload the LLM saw at any moment.
f(x) gives you the tools to engineer context effectively.
Most AI agent failures stem from poor context. f(x) makes context explicit, testable, and auditable.
npm install @fx/coreimport { step, sequence, createAgent } from '@fx/core';
// Every step is Context → Context
const analyzeStep = step('analyze', (context) => ({
...context,
analysis: `Analyzing: ${context.userInput}`,
timestamp: Date.now()
}));
const generateStep = step('generate', (context) => ({
...context,
response: `Based on: ${context.analysis}`,
confidence: 0.95
}));
// Compose steps into a workflow
const agent = createAgent('my-agent', sequence([
analyzeStep,
generateStep
]));
// Run with explicit context
const result = await agent.start({
userInput: 'Hello world'
});
console.log(result.response); // "Based on: Analyzing: Hello world"
console.log(result.confidence); // 0.95What happened:
- Each step received the complete context
- You can see exactly what data each step processed
- Context is immutable - no hidden state changes
- You can test each step independently
f(x) is a functional agent framework with these core capabilities:
Every step is a pure function Context → Context that can be composed.
// Sequential composition
const workflow = sequence([
step('analyze', (context) => ({ ...context, analysis: 'done' })),
step('generate', (context) => ({ ...context, response: 'response' }))
]);
// Parallel composition
const parallelWork = parallel([
step('readFile', readFile),
step('searchCode', searchCode)
]);
// Conditional composition
const conditional = when(
(context) => context.needsReview,
reviewStep,
skipStep
);Use the Either monad for predictable error handling.
const safeOperation = step('safeOperation', (context) => {
const result = Either.right('success');
return Either.fold(
result,
(error) => ({ ...context, error: error.message }),
(value) => ({ ...context, result: value })
);
});Immutable state transformations with lenses.
import { updateState, addState } from '@fx/core';
const updateUser = step('updateUser', (context) =>
updateState({ lastActive: Date.now() })(context)
);
const addMemory = step('addMemory', (context) =>
addState('memory', 'User updated')(context)
);Common AI agent patterns ready to use.
import { createReActPattern, createChainOfThoughtPattern } from '@fx/core';
// ReAct pattern for reasoning and acting
const reactAgent = createReActPattern('reasoning-agent');
// Chain of thought pattern
const cotAgent = createChainOfThoughtPattern('thinking-agent');Track what your agent is doing.
import { enableLogging, logEvent } from '@fx/core';
// Enable logging
enableLogging();
// Log custom events
const logStep = step('logStep', (context) => {
logEvent('user_action', { userId: context.userId });
return context;
});Every step receives explicit context. Test the exact data your AI processes.
// Test individual steps with explicit context
test('analyze step processes context correctly', () => {
const inputContext = {
userInput: 'Fix my React bug',
filePath: '/src/App.js',
previousErrors: ['TypeError: Cannot read property']
};
const result = analyzeStep(inputContext);
// Assert the exact context the LLM will see
expect(result.analysis).toContain('React bug');
expect(result.filePath).toBe('/src/App.js');
expect(result.previousErrors).toHaveLength(1);
});See exactly what context caused a failure. No more guessing.
// Every step logs its input and output context
const debugAgent = createAgent('debug-agent', plan, {
logging: true, // Logs: "Step 'analyze' received: {...}, produced: {...}"
tracing: true // Full context diff between steps
});
// When it fails, you see the exact context
// "Step 'generate' failed with context: { analysis: '...', userInput: '...' }"Track what data influenced each decision. Perfect for compliance and debugging.
// Every context change is tracked
const auditTrail = agent.getAuditTrail();
console.log(auditTrail);
// [
// { step: 'analyze', input: {...}, output: {...}, duration: 150ms },
// { step: 'generate', input: {...}, output: {...}, duration: 2000ms }
// ]Reproduce the exact context that led to any outcome.
// Save context at any point
const checkpoint = agent.saveContext();
// Later, replay from that exact state
const result = agent.replayFrom(checkpoint);
// Identical execution, guaranteedHere's a practical agent that demonstrates explicit context:
import { step, sequence, createAgent } from '@fx/core';
// Each step is Context → Context
const readCodeStep = step('readCode', async (context) => {
const fileContent = await fs.readFile(context.filePath, 'utf8');
return {
...context,
fileContent,
fileSize: fileContent.length,
readAt: Date.now()
};
});
const analyzeCodeStep = step('analyzeCode', (context) => {
const issues = findIssues(context.fileContent);
return {
...context,
issues,
severity: Math.max(...issues.map(i => i.severity)),
analysisComplete: true
};
});
const generateReviewStep = step('generateReview', (context) => {
const review = generateReviewText(context.issues, context.filePath);
return {
...context,
review,
reviewGenerated: true,
confidence: calculateConfidence(context.issues)
};
});
// Compose into a workflow
const codeReviewAgent = createAgent('code-reviewer', sequence([
readCodeStep,
analyzeCodeStep,
generateReviewStep
]));
// Run with explicit context
const result = await codeReviewAgent.start({
filePath: '/src/components/Button.tsx',
reviewType: 'security',
previousReviews: []
});
console.log(result.review); // "Found 3 security issues..."
console.log(result.confidence); // 0.87
console.log(result.issues.length); // 3What makes this powerful:
- Testable: Test each step with exact context
- Debuggable: See exactly what context caused each decision
- Auditable: Track what data influenced the review
- Replayable: Reproduce the exact same review
- Installation & Setup - Get up and running in 5 minutes
- Quick Start Guide - Build your first agent
- Context as a Value - Understanding Context as a Value
- Testing AI Agents - Test individual steps and scenarios
- Debugging & Observability - Debug with complete context visibility
- API Reference - Complete function reference
- Coding Agent - Full-featured coding assistant
- Research Agent - Advanced research and analysis
- Explicit context - See exactly what your AI processes
- Testable steps - Test individual transformations
- Debuggable failures - Know exactly what went wrong
- Auditable decisions - Track what influenced each choice
- Replayable scenarios - Reproduce any execution
- Functional composition - Build agents with pure functions
- Error handling - Use Either monad for predictable failures
f(x) is a functional framework that makes context explicit and controllable, giving you the tools to build reliable AI agents.
# Core framework
npm install @fx/core
# With OpenAI integration
npm install @fx/core openaiWe welcome contributions! Please see our Contributing Guide for details.
git clone https://github.com/skishore23/fx.git
cd fx
npm install
npm run build
npm test