Skip to Content

🧠 Active Inference

Experimental code for suggesting what to do next from a model of a person’s day. Active Inference is a Python project that is designed to keep beliefs about a person’s energy, mood, and context, update them from records of events, people, places, and content, and suggest an action by minimizing expected free energy. At v0.1.0 the main engine doesn’t run end to end: its API fails to import, and its demo and train commands fail when they create the agent. The forage sampler is the one service that starts.

Status: experimental, source only. The v0.1.0 pre-release  on GitHub attaches a source distribution and a wheel. The package isn’t on PyPI, there is no container image, it isn’t a Companion Hub app, and it has no user interface. The release notes say the install was not exercised, the test suite was not run, and the repository has no CI workflow. It isn’t connected to Companion Memory, the personal memory product. Read Limitations before you try it.

Overview

Active inference is a framework for choosing actions. An agent holds beliefs about hidden states, predicts what it will observe, and picks the action expected to reduce its uncertainty and move it toward what it prefers. This project uses the discrete form of that idea, built on the pymdp  library.

The agent in ci_active_inference/agents/__init__.py models a person like this:

PartWhat it holds
Hidden statesEnergy (low, medium, high), mood (negative, neutral, positive), and context (work, personal, social, health, learning)
ObservationsDigital behavior, location context, social context, and content
ActionsNine suggestions, such as “Take a break and rest to restore energy” and “Learn something new”
LearningDirichlet updates to the likelihood and transition matrices

The repository holds two Python packages:

  • ci_active_inference — the model above, a data access layer, a FastAPI service, and modules for explanations, monitoring, multi-step planning, and A/B testing.
  • ci_forage — a separate sampler that applies discrete active inference to a toy “memory lake”. Its example asks where a person named Sam is on Saturday. It doesn’t read Companion Memory, and it doesn’t use the agent, the database, or pymdp.

What is in the repository

  • Forage service — ./run_forage_api.sh starts the ci_forage app on port 8003, with routes such as /ask, /sample, /probe, and /resolve. It is the one service that runs as shipped.
  • Command line — python main.py takes init-db, sample-data, demo, train, or status. demo and train fail; see Limitations.
  • API service — ./run_api.sh is meant to start a FastAPI app on port 8000. At v0.1.0 the app’s module fails to import, so nothing is served. The source defines routes to create and list people, places, things, content, and events, plus /inference/predict, /inference/recommend-actions, /inference/update-beliefs, and /optimization/user-schedule/{person_id}.
  • Tests — a tests/ folder that ./run_tests.sh runs with pytest.
  • Release files — ci_active_inference-0.1.0-py3-none-any.whl and ci_active_inference-0.1.0.tar.gz, attached to the pre-release. setup.py collects Python packages with find_packages() and declares no console script or entry point, and main.py isn’t inside a package.

Technical architecture

  1. Data access: ci_active_inference/database/ connects to PostgreSQL with psycopg2, creates tables such as users, people, places, things, content, and events, and reads them through data access objects. The module’s docstring says it implements the Companion Memory server’s schema.
  2. Agent: PyMDPActiveInferenceAgent encodes the current system state as observations, infers hidden states, scores policies by expected free energy, and returns beliefs, a confidence value, and a suggested action. update_model adjusts the matrices from new observations.
  3. Service layer: main.py and ci_active_inference/api/__init__.py are written to call the agent, and both fail at v0.1.0; see Limitations. The API’s code sets cross-origin rules to allow every origin and has no authentication.
  4. Forage: ci_forage keeps the current trials in memory and writes each trial as a JSON file, named by trial ID, to the folder set with FORAGE_DATA_DIR. When that variable isn’t set, the files go to ci_forage/var/trials inside the package.

Requirements

AreaWhat the repository documents, and where the code differs
Operating systemLinux. The setup notes target Ubuntu 20.04 or later
PythonThe README and setup.py say 3.8 or later. The forage service needs 3.10 or later
ResourcesAt least 2 GB of RAM and 1 GB of free disk space
DatabasePostgreSQL, set with DATABASE_URL, for ci_active_inference. The forage service doesn’t use a database
Packagesrequirements.txt, plus the pymdp library, which the code imports but requirements.txt and setup.py don’t list. The forage service needs only NumPy, FastAPI, pydantic, and Uvicorn

Run the forage sampler

The forage service is the one part of the repository that runs as shipped. It needs Python 3.10 or later, and it doesn’t need PostgreSQL or pymdp.

Get the source

git clone https://github.com/companionintelligence/CI-Active-Inference.git cd CI-Active-Inference

Install the packages

python3 -m venv .venv source .venv/bin/activate pip install numpy fastapi pydantic uvicorn

Start the service

API_HOST=127.0.0.1 ./run_forage_api.sh # port 8003, reloads on file changes

run_forage_api.sh activates .venv or venv if one exists. It listens on all interfaces unless you set API_HOST, and it uses the port in FORAGE_PORT, which defaults to 8003. It runs Uvicorn with --reload, which keeps running after an error in the server process, so read the log if a request gets no answer.

Usage

According to the docstring in ci_forage/api.py, an empty POST /ask loads the built-in example, and one trial is current at a time. Then POST /sample reads the next item:

curl -X POST http://localhost:8003/ask curl -X POST http://localhost:8003/sample curl http://localhost:8003/trace

Open http://localhost:8003/docs for the interactive reference.

Set up the main package

The main package needs a PostgreSQL database and a release of the pymdp library that still has pymdp.maths.softmax, such as 0.0.7.1. These steps follow the repository’s README with the corrections from Limitations. They leave out demo, train, and the API, which fail as shipped. The three commands they run, init-db, sample-data, and status, don’t create the agent, but they weren’t run for this page because they need a PostgreSQL server.

export DATABASE_URL=postgresql://USER:PASSWORD@localhost:5432/ci_active_inference python3 -m venv venv source venv/bin/activate pip install -r requirements.txt "inferactively-pymdp==0.0.7.1" python main.py init-db python main.py sample-data python main.py status

The code reads environment variables and nothing in it loads the .env file, so exporting DATABASE_URL in your shell is what takes effect. The README’s ./setup.sh installs only requirements.txt and stops at its init-db step because pymdp is missing, so run these steps instead.

Limitations

The first four items were checked against v0.1.0 on 30 October 2026. Each says what was run.

  • The API doesn’t start. ci_active_inference/api/__init__.py imports get_db from ci_active_inference.database, and that module defines no get_db, so importing the API raises ImportError: cannot import name 'get_db'. Without --reload, uvicorn ci_active_inference.api:app exits with that error. ./run_api.sh adds --reload by default, so it prints Uvicorn running on ... and starts a reloader, but the server process dies with the same error and the reloader keeps waiting for file changes. No request is answered, not even the interactive documentation at /docs. Checked on Python 3.12 with requirements.txt installed, by importing the module and by starting it with uvicorn, and by running ./run_api.sh with API_HOST=127.0.0.1 on Python 3.9.
  • demo and train fail. Both create the tables and sample data, then call CIActiveInferenceAgent() with no arguments. demo goes on to call predict_future_state and recommend_actions, and train calls update_beliefs. The class that name refers to, PyMDPActiveInferenceAgent, requires a user_id and defines none of those methods. The functions behind both commands raise TypeError: PyMDPActiveInferenceAgent.__init__() missing 1 required positional argument: 'user_id' as soon as they create the agent. SimpleActiveInferenceAgent in agents/simple_agent.py defines the methods the commands call. Checked by calling those functions on Python 3.12 with inferactively-pymdp 0.0.7.1 installed, without a database.
  • pymdp isn’t declared, and its current release doesn’t fit. ci_active_inference/agents/__init__.py imports pymdp, but requirements.txt and setup.py don’t list it. On a clean install, main.py stops with ModuleNotFoundError: No module named 'pymdp', and so does ./setup.sh. The package named pymdp on PyPI is an unrelated project. The library is published as inferactively-pymdp, and the repository pins no version. The imports in agents/__init__.py work with inferactively-pymdp 0.0.7.1. With 1.0.4, from pymdp.maths import softmax raises ImportError. Checked with ./setup.sh on Python 3.9, and with main.py and the imports on Python 3.12. The agent’s behavior was not checked.
  • The forage service needs Python 3.10 or later. ci_forage/api.py annotates its request models with str | None. On Python 3.9, importing it raises TypeError: Unable to evaluate type annotation 'str | None'. run_forage_api.sh uses --reload, so it still prints Uvicorn running on ..., the server process dies with that error, and requests get no answer. The README and setup.py say 3.8 or later, and inferactively-pymdp 1.0.x also needs 3.10 or later. Checked by importing the module and by running run_forage_api.sh on Python 3.9.6.
  • PostgreSQL, not SQLite. The README and SETUP.md describe SQLite as the default database and mention DATABASE_PATH. The database module that main.py and the API use connects to PostgreSQL through psycopg2, and nothing in main.py or the API reads DATABASE_PATH.
  • No supported install. The wheel and source distribution were built from the v0.1.0 tag, but the release notes say the install was not exercised and the test suite was not run. There is no CI workflow.
  • No authentication. Neither service has a sign-in. The main API’s code allows requests from any origin, and both run scripts listen on all interfaces unless you set API_HOST. Run them only on a network you trust.
  • Not connected to Companion Memory or Hub. The code makes no calls to the Companion Memory API or any other service over HTTP. It reads the database you point it at. It isn’t a Hub app and has no Marketplace entry.
  • No user interface. The README’s plan describes a web front end. None is in the repository.
  • The roadmap is a plan. The README’s 16-week checklist has 30 items and none is checked off, so it doesn’t tell you which parts are built.

License

Companion Active Inference is free for noncommercial and research use under the PolyForm Noncommercial License 1.0.0 . Commercial use, including paid access to a hosted instance, isn’t permitted. See the repository’s License FAQ .

Last updated on