Use this guide to choose a default stack quickly, then tune for cost and reliability.
Start with a profile
Section titled “Start with a profile”The fastest way to compose capabilities is a HarnessProfile preset — it sets the default-on capability bundle in one line, and you override individual pieces afterward (later calls win). The declarative equivalent is the profile config key. (HarnessProfile ships in v0.12+; on earlier versions use the explicit .with*() chain below.)
import { createAgent } from "reactive-agents";
const agent = await createAgent({ name: "production-agent", provider: "anthropic", profile: "balanced", // memory + RI + verifier + strategy switching tools: { builtins: true },});import { ReactiveAgents, HarnessProfile } from "reactive-agents";
const agent = await ReactiveAgents.create() .withName("production-agent") .withProvider("anthropic") .withProfile(HarnessProfile.balanced()) // memory + RI + verifier + strategy switching .withTools({ builtins: true }) .build();| Preset | Use when |
|---|---|
HarnessProfile.lean() | Latency/cost-sensitive paths or ablations — model only, all default capabilities off. |
HarnessProfile.balanced() | Most production apps — the full stack (memory + reactive intelligence + verifier + strategy switching). Memory is off in a bare builder as of v0.12; balanced() enables it explicitly. |
HarnessProfile.intelligent() | You want cross-session compounding learning — balanced + skill persistence. |
Override after the preset: .withProfile(HarnessProfile.lean()).withMemory() re-enables just memory (declaratively, profile: "lean" alongside a memory: {} key does the same — explicit keys always win over the preset).
Default Recommendation
Section titled “Default Recommendation”For most production apps, the equivalent explicit chain:
const agent = await createAgent({ name: "production-agent", provider: "anthropic", model: "claude-sonnet-4-6", reasoning: { defaultStrategy: "adaptive" }, tools: { builtins: true }, memory: {}, guardrails: {}, costTracking: {}, observability: { verbosity: "normal" },});const agent = await ReactiveAgents.create() .withName("production-agent") .withProvider("anthropic") .withModel("claude-sonnet-4-6") .withReasoning({ defaultStrategy: "adaptive" }) .withTools({ builtins: true }) .withMemory() .withGuardrails() .withCostTracking() .withObservability({ verbosity: "normal" }) .build();Decision Matrix
Section titled “Decision Matrix”| Decision | Start here | Move when |
|---|---|---|
| Provider | Anthropic | You need local/offline (ollama) or existing proxy infra (litellm) |
| Model tier | Mid/high capability | Latency or budget pressure dominates quality |
| Memory tier | Tier 1 | You need semantic similarity retrieval (Tier 2 vectors) |
| Reasoning strategy | Adaptive | Workload is consistent and you want deterministic behavior |
| Tools | Built-ins only | You need external systems via MCP/custom tools |
Strategy Selection Cheat Sheet
Section titled “Strategy Selection Cheat Sheet”| Workload | Strategy |
|---|---|
| API automation / deterministic tool work | reactive |
| Long multi-step tasks with explicit plans | plan-execute-reflect |
| Exploration and branching ideas | tree-of-thought |
| Self-critique and iterative improvement | reflexion |
| Mixed unknown workloads | adaptive |
Cost-First vs Quality-First Profiles
Section titled “Cost-First vs Quality-First Profiles”Cost-first profile
Section titled “Cost-first profile”The .withContextProfile() override is builder-only — it has no declarative config key, so the cost-first tuning knob stays in code:
const agent = await ReactiveAgents.create() .withName("cost-first-agent") .withProvider("ollama") .withModel("qwen3:4b") .withContextProfile({ tier: "local", toolResultMaxChars: 800 }) .withReasoning({ defaultStrategy: "reactive" }) .withMaxIterations(6) .build();Quality-first profile
Section titled “Quality-first profile”Everything else in a quality-first stack is declarative too:
const agent = await createAgent({ name: "quality-first-agent", provider: "anthropic", model: "claude-sonnet-4-6", reasoning: { defaultStrategy: "adaptive" }, memory: { tier: "enhanced" }, verification: {}, execution: { maxIterations: 20 },});const agent = await ReactiveAgents.create() .withName("quality-first-agent") .withProvider("anthropic") .withModel("claude-sonnet-4-6") .withReasoning({ defaultStrategy: "adaptive" }) .withMemory({ tier: "enhanced" }) .withVerification() .withMaxIterations(20) .build();Team-Based Starting Points
Section titled “Team-Based Starting Points”Internal copilots
Section titled “Internal copilots”- Guardrails + identity + audit
- Tier 1 memory
- Adaptive strategy
- Normal observability
Autonomous operations agents
Section titled “Autonomous operations agents”- Gateway + policies + kill switch
- Strong budgets and alerts
- Event subscriptions for suppression/exhaustion events
Research/reporting agents
Section titled “Research/reporting agents”- Tools + verification + memory tier 2
- Plan-execute or reflexion
- Higher max iterations
Anti-Patterns to Avoid
Section titled “Anti-Patterns to Avoid”- Turning on all layers before proving need
- Using
tier: "enhanced"memory without an embedding provider configured - Long max iterations without budget controls
- MCP subprocess usage without guaranteed disposal