FAIR-LLM: A Flexible, Agnostic, and Interoperable Reasoning Framework
FAIR-LLM is a Python framework designed to accelerate the development of powerful, consistent, and modular agentic applications. It provides a structured, interface-driven architecture that allows developers to easily build and customize agents with sophisticated reasoning capabilities, long-term memory, and collaborative multi-agent systems. Crafted to help engineers build powerful AI systems without vendor lock-in.
Core Principles
The FAIR framework is built on four core principles that guide its architecture and empower developers:
- Flexible: The framework is highly modular. Every core component is built upon an abstract interface, allowing developers to easily swap implementations (e.g., swapping a simple memory system for a summarizing one) without altering the agent's core logic.
- Agnostic: You are not locked into a single LLM provider. The Model Abstraction Layer (MAL) enables seamless switching between different models—from OpenAI and Anthropic to local models via HuggingFace or Ollama—ensuring you can always use the best tool for the job.
- Interoperable: Components are designed to work together seamlessly. A standardized set of data structures, like the
MessageandDocumenttypes, ensures that data flows consistently between the agent's memory, planner, and tools. - Reasoning: At its heart, the framework is built to support sophisticated reasoning patterns. The default
ReActPlannerallows agents to "think" step-by-step to solve complex problems, and the architecture is extensible enough to support more advanced paradigms like "Plan-and-Execute".
Key Features
- Advanced Agent Patterns: Built-in support for the powerful ReAct (Reason+Act) cognitive cycle. Two planner variants are provided:
ReActPlanner(JSON-based, for powerful models like GPT-4 and Claude) andSimpleReActPlanner(key-value format, for smaller or local models that may struggle with strict JSON). - Multi-Agent Collaboration: Orchestrate teams of specialized agents with workers-as-tools fan-out.
WorkerAgentToolwraps any agent as a typed tool andbuild_worker_managerwires a manager that delegates independent sub-tasks concurrently in a single turn, enabling the system to tackle complex, multi-faceted problems. - Retrieval-Augmented Generation (RAG): Easily ground agents in your own documents and data. The framework includes all necessary components for a robust RAG pipeline, including document loaders, text splitters, embedders (
SentenceTransformerEmbedder), and two queryable vector store backends (FaissVectorStoreandChromaDBVectorStore) made available to the agent through theKnowledgeBaseQueryTool. FAISS is the recommended default backend. - Pluggable Model Support: The Model Abstraction Layer (MAL) features concrete adapters for OpenAI, Anthropic, HuggingFace Transformers, Ollama (local models), and LoadBalancerAdapter (distributed vLLM inference clusters), allowing for unparalleled flexibility in model selection and deployment topology.
- Modular & Extensible by Design: Every core component (LLM, Memory, Tools, Planner) is defined by an
Abstractbase class in thecore/interfaces/directory. This interface-driven design makes the framework easy to extend and customize. - Prompt Engineering System: A first-class prompt engineering system lives in
core/prompts/, providing composable building blocks:PromptBuilder,RoleDefinition,FormatInstruction,Example,ToolInstruction,WorkerInstruction, and more. Planners merge their own mandatory format instructions with the application content these blocks provide, so prompt content and parse format cannot drift apart. - MCP (Model Context Protocol) Integration: A full
modules/mcp/package provides first-class support for MCP tool servers. Agents can combine local FAIR tools with tools from any MCP-compatible server (stdio or SSE transport) usingMCPToolRegistry,CompositeToolRegistry, andcreate_mcp_enhanced_registry. Configure MCP connections viaMCPServerConfiginsettings.yml. - Streaming Responses: Opt-in end-to-end token streaming through the agent loop. Enable
streaming.enabled(or passstream=Trueto a planner orSimpleAgent) and every model call is consumed incrementally and published as typed events (ModelStreamStartEvent,ModelStreamChunkEvent,ModelStreamEndEvent) on the agent event bus, withKVFinalAnswerStreamFilterextracting just the final-answer text for chat surfaces. The run's return value is unchanged. Seedemos/demo_streaming_agent.py. - Secure by Design: The framework includes foundational components for security, such as the
BasicSecurityManagerfor input validation and explicit warnings and placeholders for sandboxed tool execution to mitigate risks. - Reliable Structured Output: Comes with patterns and demos (see
demo_structured_output.py) for compelling LLMs to return clean, Pydantic-validated JSON, which is essential for reliable data extraction and tool integration. - Agent Configuration Persistence: Save and reload complete agent configurations — including prompt definitions, tool setup, and model settings — via utilities in
fairlib.modules.agent.factory. Enables reproducible agent setups, team sharing, and prompt optimization workflows.
Getting Started: Your First Agent (5-Minute Quickstart)
Follow these steps to get your first agent running.
1. Prerequisites
- Python 3.12+
- Git
2. Installation
Install warning: This framework is published on PyPI as
fair-llm(hyphen), imported in Python asfairlib. The unrelated PyPI packagefairlib(0.1.0) is a different project. Always pin the correct distribution, e.g.fair-llm==0.6.0inrequirements.txtorconstraints.txt, and verify withpip show fair-llmbefore debugging import errors.
Package name vs import name: install with pip install fair-llm (hyphen). Import in Python as import fairlib. The unrelated PyPI package fairlib (0.1.0) is not this framework; pin fair-llm==0.6.0 in constraints.txt to avoid the footgun.
The slim core install ships anthropic and httpx as first-class dependencies so OpenAI, Anthropic, and Ollama adapters work without optional extras.
Clone the repository and install the required dependencies. It is highly recommended to use a virtual environment.
git clone https://github.com/USAFA-AI-Center/fair_llm.git
cd fair_llm
pip install -e .
For the default slim install (OpenAI, Anthropic, Ollama adapters without local torch/RAG), use:
pip install -e .
For local HuggingFace models (torch, transformers):
pip install -e ".[local]"
For RAG (chromadb, sentence-transformers, faiss):
pip install -e ".[rag]"
For the full stack (local HuggingFace models plus RAG; [all] adds faiss-cpu on top of [local]; anthropic is in the base install):
pip install -e ".[all]"
Network egress allowlist: BasicSecurityManager(allowed_egress=...) and tool
network_egress declarations validate declared targets only. This is NOT a network
sandbox: tools must call validate_network_egress inside acall for input-derived
hosts, and the default posture permits all egress until you opt into an allowlist.
Configure the allowlist in YAML (security.allowed_egress) or at construction:
from fairlib import settings
from fairlib.modules.security.basic_security_manager import BasicSecurityManager
security = BasicSecurityManager.from_settings(settings)
Or pass allowed_egress=settings.security.allowed_egress explicitly.
A requirements.txt is provided in the repository root for development installs with the full dependency set.
3. Configuration
The framework uses a centralized YAML configuration file for API keys and model settings.
- Either edit the packaged file at
fairlib/config/settings.yml, or setFAIR_LLM_SETTINGSto a consumer-owned YAML path, or callconfigure_settings(path=...)to replace the module singleton, or pass explicit kwargs when constructing adapters. Whoever controls the process environment controls which YAML is loaded (including security-related fields); parsing usesyaml.safe_loadonly. - Add your API keys (e.g., for OpenAI or Anthropic).
- Review the model definitions and other settings (RAG paths, cache, security, MCP) to suit your environment.
Local Ollama + SimpleReActPlanner
SimpleReActPlanner uses a simplified key-value response format for smaller local models that struggle with strict JSON. The agent loop tolerates consecutive PlannerParseError failures up to SimpleAgent(max_parse_attempts=...) (default 2 total parse tries before abort). Retryable transient tool failures can be retried within a turn via SimpleAgent(max_tool_retries=...) (default 0; set to a positive value to enable).
| Model | Typical outcome with SimpleReActPlanner |
|---|---|
qwen2.5:14b |
Reliable KV compliance; completes chat turns and invokes tools correctly |
llama3.2 (3B) |
Usually completes turns; occasional malformed KV fields |
llama3:8b, llama3.1:8b |
Not supported for interactive agent chat — exhaust max_parse_attempts and abort on typical first messages; format compliance tracks the model's instruction tuning, not its parameter count |
llama3.2:1b |
Not supported for interactive agent chat — hard-fails after max_parse_attempts on most chat-path runs |
deepseek-r1:7b |
Generally usable when Ollama serves the model reliably |
1B models: Do not use llama3.2:1b (or similar 1B checkpoints) with SimpleReActPlanner for capstone-style agent chat. They lack reliable KV compliance. Prefer 3B+ for local agent loops, or switch to ReActPlanner (JSON) with a cloud model when format compliance is critical. If you must experiment with 1B, raise max_parse_attempts and expect frequent aborts — that is a degrade path, not a supported configuration.
3B tool_input mangling: Executor smoke tests (tool.acall / tool.invoke / direct ToolExecutor calls) validate tool wiring only; they do not exercise planner format compliance on the chat path. When tool_input arrives malformed from the model, use ReActPlanner (JSON) or a larger local model rather than trusting executor-only tests.
Recommendations: prefer 3B+ models for interactive agent chat; use ReActPlanner (JSON) with cloud models when format compliance is critical; increase max_parse_attempts if you accept longer re-prompt loops on borderline models. Validate chat-path behavior separately from tool-only smoke tests.
4. Run Your First Agent
The following code assembles and runs a simple agent that can use a calculator. Save it as main.py in the root of the project directory.
# main.py
import asyncio
from fairlib import (
settings,
OpenAIAdapter,
ToolRegistry,
SafeCalculatorTool,
ToolExecutor,
WorkingMemory,
ReActPlanner,
SimpleAgent
)
async def main():
print("Initializing a single agent...")
# 1. The "Brain": Initialize the LLM adapter from the settings file
llm = OpenAIAdapter(
api_key=settings.api_keys.openai_api_key,
model_name=settings.models["openai_gpt4"].model_name
)
# 2. The "Toolbelt": Create a registry and add tools
tool_registry = ToolRegistry()
tool_registry.register_tool(SafeCalculatorTool())
# 3. The "Hands": Create an executor that uses the toolbelt
executor = ToolExecutor(tool_registry)
# 4. The "Memory": Set up short-term memory for the conversation
memory = WorkingMemory()
# 5. The "Mind": Create the planner that uses the brain and tools
planner = ReActPlanner(llm, tool_registry)
# 6. Assemble the Agent: Combine all parts into a functional unit
agent = SimpleAgent(
llm=llm,
planner=planner,
tool_executor=executor,
memory=memory
)
print(" Agent created. Ask a math question or type 'exit'.")
# 7. Run the agent in a loop
while True:
try:
user_input = input("\n You: ")
if user_input.lower() == "exit":
break
response = await agent.arun(user_input)
print(f" Agent: {response}")
except KeyboardInterrupt:
break
if __name__ == "__main__":
asyncio.run(main())
Run the agent from your terminal:
python main.py
Security
Network egress policy is opt-in and layered; it is not a sandbox.
What the allowlist checks: static network_egress tuples declared on each tool
at registration time (when reaches_network=True), plus any runtime
validate_network_egress calls tools make for input-derived hosts inside acall.
SideEffect.EXTERNAL_READ: idempotent network reads (WebSearcherTool, etc.)
may run concurrently when tool_dispatch.parallel_read_only is enabled. Tools must
use async I/O (or asyncio.to_thread for blocking clients) or parallelism only
schedules overlap without speeding up blocking calls.
Shipped tools: WebSearcherTool declares Google PSE egress; grading tools derive
egress from the injected MAL adapter; WebDataExtractor validates fetch URLs at
runtime; WorkerAgentTool is in-process by default (reaches_network=False);
MCP SSE adapters declare transport hosts (stdio MCP uses
VERIFIED_NO_AGENT_SIDE_EGRESS).
Compensating controls you still need: OS/network firewalls, secret management,
MCP server trust boundaries, sandboxed code execution (the shipped
BasicSecurityManager.asandbox_code_execution is a demo stub), and reviewing tool
implementations for undeclared outbound calls. Multi-agent setups must set
security_manager on each agent level (build_worker_manager forwards the
manager's policy recursively to nested worker executors).
Point the framework at your own config instead of the packaged settings.yml:
export FAIR_LLM_SETTINGS=/path/to/your/settings.yml
Or construct adapters with explicit kwargs and skip the fairlib.settings singleton.
Learn with Demos
The demos/ directory contains executable scripts that are the best way to learn the framework's capabilities.
demo_single_agent_calculator.py: The best place to start. Learn the fundamentals of building and running a single agent with a simple tool.demo_advanced_calculator_calculus.py: Shows how to equip an agent with multiple, more complex tools.demo_rag_from_documents.py: A deep dive into Retrieval-Augmented Generation using ChromaDB.demo_faiss_rag_from_readme.py: RAG using the FAISS vector store backend with cross-encoder re-ranking (recommended for most use cases).demo_structured_output.py: Learn how to reliably extract structured JSON data from unstructured text, complete with Pydantic validation and a self-correction loop.demo_model_comparison.py: See the Model Abstraction Layer in action by comparing responses from different LLMs side-by-side.demo_multi_agent.py: The most advanced agent demo. Learn how to orchestrate a team of specialized agents to solve a complex problem that's impossible for a single agent.demo_committee_of_agents_*.py: Practical examples of the multi-agent architecture applied to autograding essays and code.demo_web_search_plot_agent.py: An agent that combines web search and graphing tools to answer data-driven questions.
Learn with Our Developer's Guide
Our comprehensive developer's guide, "A Guide to the FAIR Agentic Framework", is written for developers of all skill levels—from newcomers to experienced AI engineers. Whether you're building your first chatbot with a tool or architecting a complex network of distributed agents, this guide will give you the principles and practical techniques you need. The guide is available in the docs/ directory.
Framework Architecture
The FAIR Agentic Framework is organized into a modular architecture. Below is an overview of the most critical components:
core/: Contains the architectural DNA of the framework.interfaces/: Abstract Base Classes defining the "contract" for every major component (AbstractChatModel,AbstractPlanner,AbstractMemory,AbstractTool,AbstractEmbedder,AbstractPerception,AbstractSecurityManager). This is the key to the framework's modularity.message.py: Core conversational data structures —Message,Thought,Action,Observation, andFinalAnswer— that flow between all components.types.py: Domain data types such asDocument,GradingCriterion, andFinalGrade.prompts/: The prompt engineering package — prompt item types initems.py, builders inbuilders.py, and lazy compatibility re-exports from__init__.py.Historynow lives under memory andAgentCapabilityunder the capability surface while remaining importable fromfairlib.core.prompts.base_agent.py: The abstractBaseAgentclass all agents inherit from.config.py/config_schemas.py: Pydantic-validated configuration loading, includingMCPServerConfigandMCPSettingsschemas.
modules/: Contains the concrete implementations of the interfaces.mal/: The Model Abstraction Layer, with adapters forOpenAIAdapter,AnthropicAdapter,OllamaAdapter,HuggingFaceAdapter, andLoadBalancerAdapter(distributed vLLM inference).agent/: Agent definitions (SimpleAgent), the workers-as-tools fan-out path (WorkerAgentTool,build_worker_manager), and the agent factory (factory- build agents from config files, save them back).planning/: Reasoning engines —ReActPlanner(JSON-based, for powerful models),SimpleReActPlanner(key-value format, for smaller/local models), andMultiActionReActPlanner(several tool calls per turn), all sharingBaseTextPlanner. Planners contribute only their mandatory format rules and the live tool/worker catalog to the prompt - all other content (role, examples) is supplied by your application.mcp/: Full Model Context Protocol support —MCPClient,MCPToolAdapter,MCPToolRegistry,MCPServer, andcreate_mcp_enhanced_registry. Supports bothstdioandSSEtransports.action/: TheToolExecutor,ToolRegistry,CompositeToolRegistry(merges multiple registries for hybrid local+MCP setups), and the tool library — built-in tools (SafeCalculatorTool,WebSearcherTool,WeatherTool,GraphingTool,WebDataExtractor) and domain tools (KnowledgeBaseQueryTool,GradeEssayFromRubricTool,GradeCodeFromRubricTool,CodeExecutionTool,AdvancedCalculusTool).memory/: Short-term (WorkingMemory,SummarizingMemory) and long-term/RAG memory components (FaissVectorStore— import viafairlib.modules.memory.vector_faiss,ChromaDBVectorStore,InMemoryVectorStore,SentenceTransformerEmbedder,SimpleRetriever,retriever_rerank).perception/: Input preprocessing components (TextParser,EchoPreprocessor).communication/: Agent-to-agent communication (InMemoryCommunicator).learning/: Model selection and learning utilities.security/: Security components like theBasicSecurityManager.
config/: Centralized YAML configuration (settings.yml), including MCP server configuration.utils/: Utility code —document_processor,autograder_utils,math_expression_parser,rag_prompts,chart_utils,WolframGPT, and more.fairlib/__init__.py: The central, user-facing API providing lazy-loaded access to all framework components.demos/: A collection of scripts that serve as practical, executable examples of the framework's capabilities.
Folder Structure
fair_llm/
├── fairlib/
│ ├── config/
│ │ └── settings.yml
│ ├── core/
│ │ ├── interfaces/
│ │ │ ├── communicator.py
│ │ │ ├── embedder.py
│ │ │ ├── executor.py
│ │ │ ├── llm.py
│ │ │ ├── memory.py
│ │ │ ├── model_manager.py
│ │ │ ├── perception.py
│ │ │ ├── planner.py
│ │ │ ├── security.py
│ │ │ └── tools.py
│ │ ├── base_agent.py
│ │ ├── config.py
│ │ ├── config_schemas.py (includes MCPServerConfig, MCPSettings)
│ │ ├── message.py
│ │ ├── prompts/ (prompt items + builders + compatibility re-exports)
│ │ └── types.py
│ ├── modules/
│ │ ├── action/
│ │ │ ├── tools/
│ │ │ │ ├── builtin_tools/
│ │ │ │ │ ├── data_extractor.py
│ │ │ │ │ ├── final_answer.py
│ │ │ │ │ ├── safe_calculator.py
│ │ │ │ │ ├── weather.py
│ │ │ │ │ └── web_searcher.py
│ │ │ │ ├── advanced_calculus_tool.py
│ │ │ │ ├── code_execution_tool.py
│ │ │ │ ├── composite_registry.py (CompositeToolRegistry)
│ │ │ │ ├── grading_tool.py
│ │ │ │ ├── graphing_tool.py
│ │ │ │ ├── knowledge_tool.py
│ │ │ │ └── registry.py
│ │ │ └── executor.py
│ │ ├── agent/
│ │ │ ├── factory.py (save_agent_config, load_agent)
│ │ │ ├── simple_agent.py
│ │ │ ├── worker_manager.py (build_worker_manager)
│ │ │ └── worker_tool.py (WorkerAgentTool)
│ │ ├── communication/
│ │ │ └── in_memory_communicator.py
│ │ ├── learning/
│ │ │ ├── base.py
│ │ │ └── model_selector.py
│ │ ├── mal/
│ │ │ ├── anthropic_adapter.py
│ │ │ ├── huggingface_adapter.py
│ │ │ ├── load_balancer_adapter.py (LoadBalancerAdapter — vLLM)
│ │ │ ├── local_llama_adapter.py (OllamaAdapter)
│ │ │ └── openai_adapter.py
│ │ ├── mcp/
│ │ │ ├── client/
│ │ │ │ ├── mcp_client.py
│ │ │ │ ├── mcp_tool_adapter.py
│ │ │ │ └── mcp_tool_registry.py
│ │ │ └── server/
│ │ │ └── mcp_server.py
│ │ ├── memory/
│ │ │ ├── base.py
│ │ │ ├── embedder.py
│ │ │ ├── retriever.py
│ │ │ ├── retriever_rerank.py
│ │ │ ├── summarization.py
│ │ │ ├── vector_faiss.py
│ │ │ └── vector_store.py (ChromaDB)
│ │ ├── perception/
│ │ │ ├── echo_preprocessor.py
│ │ │ └── text_parser.py
│ │ ├── planning/
│ │ │ ├── base_text_planner.py (shared planner shell + prompt cache)
│ │ │ ├── multi_action_planner.py (MultiActionReActPlanner)
│ │ │ ├── react_planner.py (ReActPlanner)
│ │ │ └── simple_react_planner.py (SimpleReActPlanner)
│ │ └── security/
│ │ └── basic_security_manager.py
│ ├── utils/
│ │ ├── autograder_utils.py
│ │ ├── chart_utils.py
│ │ ├── document_processor.py
│ │ ├── math_expression_parser.py
│ │ ├── nuextract.py
│ │ ├── rag_prompts.py
│ │ ├── speech_util.py
│ │ └── WolframGPT.py
│ └── __init__.py (central API with lazy loading)
├── demos/
├── docs/
│ ├── Agentic System Design Blueprint.pdf
│ ├── fair_lib_dev_doc.pdf
│ └── latex/
├── tests/
├── Jenkinsfile
├── LICENSE.md
├── pyproject.toml
├── README.md
├── requirements.txt
└── uv.lock
Contributors
Developed by the USAFA AI Center team:
- Ryan R (rrabinow@uccs.edu)
- Austin W (austin.w@ardentinc.com)
- Eli G (elijah.g@ardentinc.com)
- Chad M (Chad.Mello@afacademy.af.edu)
Contributing
Contributions are welcome! Please open an issue or submit a pull request with any enhancements, bug fixes, or new features.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fair_llm-0.6.1.tar.gz.
File metadata
- Download URL: fair_llm-0.6.1.tar.gz
- Upload date:
- Size: 580.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ccd3ebf1ad160c4bc8d1f8f3b8aa8a13b409c1e414c821a4a5a973938b5a30f8
|
|
| MD5 |
092e6bdbd2c5f3a639cdbb950489ed53
|
|
| BLAKE2b-256 |
b0d2b5cfe7c99febbfb1ad8d70d16d464d08211f52f283949a7dbd3a2d076e3e
|
File details
Details for the file fair_llm-0.6.1-py3-none-any.whl.
File metadata
- Download URL: fair_llm-0.6.1-py3-none-any.whl
- Upload date:
- Size: 700.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b250ca3059d05db24128ffde0be1f7826e206389559adcf8c1c253d0f1d63a88
|
|
| MD5 |
a36ea2155c20f110b6785ad3cbda9327
|
|
| BLAKE2b-256 |
48d6315bf661cac35e60154a147597c5f7c81136aaa168e69c5e216041f9f2fe
|