A biologically-inspired reactive agent framework for Python
Project description
Arachnite
A biologically-inspired reactive agent framework for Python.
The architecture models the nervous system of arachnids — sense → context → reflex → instinct → decide → act. Developers extend abstract base classes
to build agents that run on edge devices (Raspberry Pi, Jetson Nano), laptops,
or cloud servers, all connected by a pluggable transport layer.
- Async-first: every node interface is
asyncio-native - Typed: strict type annotations throughout (mypy strict)
- Pluggable transports: in-process, MQTT, NATS, Redis
- Distributed by manifest: declarative multi-device deployment
- Reflex co-location: safety-critical reflexes are validated at deploy time
- Python 3.10+
Install
pip install arachnite
With optional extras:
pip install "arachnite[all]" # every optional dependency
pip install "arachnite[mqtt]" # MQTT transport
pip install "arachnite[nats]" # NATS transport
pip install "arachnite[redis]" # Redis transport
pip install "arachnite[web]" # bundled signal dashboard
pip install "arachnite[llm]" # Anthropic LLM provider
pip install "arachnite[benchmarks]" # psutil for RSS measurement
Development install from source:
git clone https://github.com/memrecolak/arachnite-oss.git arachnite
cd arachnite
pip install -e ".[all,dev]"
Quick start
A minimal agent: a sensor that reads temperature, an instinct that fires when it gets hot, and an action that cools things down.
import asyncio
import time
from arachnite import (
BaseActionNode,
BaseInstinctNode,
BaseSenseNode,
Proposal,
Result,
RuntimeBuilder,
Signal,
)
class TempSense(BaseSenseNode):
node_id = "TempSense"
signal_kind = "temperature"
async def read(self) -> Signal:
return Signal(
source=self.node_id,
kind=self.signal_kind,
value=42.0,
confidence=1.0,
timestamp=time.monotonic(),
)
class HotInstinct(BaseInstinctNode):
node_id = "HotInstinct"
priority = 80
async def evaluate(self, ctx) -> Proposal | None:
hot = [s for s in ctx.signals if s.kind == "temperature" and s.value > 40.0]
if hot:
return Proposal(
instinct_id=self.node_id,
action_id="CoolDown",
priority=self.priority,
urgency=0.9,
)
return None
class CoolDown(BaseActionNode):
node_id = "CoolDown"
async def execute(self, proposal) -> Result:
print(f"Cooling down! params={proposal.parameters}")
return Result(action_id=self.node_id, success=True)
async def main() -> None:
rt = (
RuntimeBuilder()
.sense(TempSense)
.instinct(HotInstinct)
.action(CoolDown)
.tick_rate(5.0)
.build()
)
await rt.start()
await asyncio.sleep(5.0)
await rt.stop()
asyncio.run(main())
See the examples/ directory for more complete programs:
reflex nodes, multi-step actions, supervisor restart policies, and a
web dashboard.
Documentation
tutorials/— step-by-step lessons starting at tutorials/01_welcome.md. Advanced topics (multi-step actions, supervisors, distributed deployment, LLM instincts, active inference, safety monitors) live undertutorials/advanced/.spec/— the formal framework specification, eight numbered sections covering architecture, nodes, runtime, distributed deployment, infrastructure, and the benchmark suite.
Core concepts
Nodes
Five node families, each with an abstract base and a master that owns the registered instances:
| Node | Returns | When to use |
|---|---|---|
BaseSenseNode |
Signal |
Read hardware/state, emit one signal per tick |
BaseInstinctNode |
Proposal or None |
Evaluate context, propose an action |
BaseReflexInstinctNode |
Proposal or None |
Same as instinct, but bypasses the decision layer (priority ≥ 200, co-located with target action) |
BaseDecisionNode |
Decision |
Pick which proposal to execute (Greedy / Weighted / Random / ActiveInference built-ins, or your own) |
BaseActionNode |
Result |
Carry out the work — must always return, never raise |
MultiStepActionNode |
Result |
Long-running actions with interrupt/rollback policies |
Priority convention
- 200+ — reflex instincts only
- 100–199 — safety / survival
- 50–99 — goal-directed
- 1–49 — exploratory / maintenance
- 0 — reserved (inactive)
Architectural rules
- Nodes never hold references to each other; communication goes through
SignalBus. ReflexInstinctNodeand its targetActionNodemust be on the sameAgentNode.MultiStepActionNodemandatory blocks cannot be interrupted (exceptemergency_stop).execute()on anyActionNodemust always return aResult— never raise.evaluate()on anyInstinctNodemust returnNonewhen not applicable — never raise.- All node I/O must be async — wrap blocking hardware calls in
asyncio.to_thread().
Distributed deployments
A DeploymentManifest declares which nodes run on which AgentNode. The
manifest validator enforces co-location rules and fails loudly on missing
environment variables.
agents:
vision:
transport: nats
transport_url: ${NATS_URL}
nodes:
- ProximitySense
- ObjectDetectionSense
control:
transport: nats
transport_url: ${NATS_URL}
nodes:
- JointPositionSense
- CollisionReflex # priority 250, reflex
- EmergencyRetract # co-located target
- GraspInstinct
- PickAndPlace
See examples/robot_arm/ for a runnable two-agent
case study.
Benchmarks
A reproducible benchmark suite ships under benchmarks/:
# Full suite (30 runs, JSON output)
python benchmarks/suite.py
# Quick run (5 runs)
python benchmarks/suite.py --runs 5
# Individual benchmarks
python benchmarks/tick_latency.py
python benchmarks/reflex_latency.py
python benchmarks/scalability_sweep.py
python benchmarks/transport_latency.py
Benchmarks include tick latency, per-stage breakdown, reflex arc timing, memory footprint, scalability sweeps, multi-step action interrupt latency, long-horizon stability soak, and transport publish-to-deliver latency. All emit JSON with bootstrap CIs for median / P95 / P99.
Cross-framework comparison (optional)
baselines/ holds comparison harnesses against
py_trees,
ROS 2, and the Jason
AgentSpeak BDI engine. These are not part of the framework — they are
not installed by pip install arachnite and are excluded from the wheel.
They require external toolchains (JVM, ROS 2) to run. See
baselines/README.md for setup.
Development
# Run all tests
pytest
# With coverage
pytest --cov=arachnite --cov-report=term-missing
# Type check
mypy arachnite
# Lint
ruff check arachnite tests benchmarks
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
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 arachnite-0.11.2.tar.gz.
File metadata
- Download URL: arachnite-0.11.2.tar.gz
- Upload date:
- Size: 5.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ac50712715f12bb62a91092f02c42b3b6d8e96a8fbfb7e54762758827bd8a47
|
|
| MD5 |
7a6f782045c145e544347c5f16e3d4c1
|
|
| BLAKE2b-256 |
0950a549eee358bae83067e9dbcd0f09bc11b0686124fc99372c00de87e5d54c
|
Provenance
The following attestation bundles were made for arachnite-0.11.2.tar.gz:
Publisher:
publish.yml on memrecolak/arachnite-oss
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arachnite-0.11.2.tar.gz -
Subject digest:
3ac50712715f12bb62a91092f02c42b3b6d8e96a8fbfb7e54762758827bd8a47 - Sigstore transparency entry: 1591266027
- Sigstore integration time:
-
Permalink:
memrecolak/arachnite-oss@8bf274b705ed0fde655f1fd4664817599a1d4c4b -
Branch / Tag:
refs/tags/v0.11.2 - Owner: https://github.com/memrecolak
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8bf274b705ed0fde655f1fd4664817599a1d4c4b -
Trigger Event:
push
-
Statement type:
File details
Details for the file arachnite-0.11.2-py3-none-any.whl.
File metadata
- Download URL: arachnite-0.11.2-py3-none-any.whl
- Upload date:
- Size: 5.6 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7bc1ab6c7d16b6d40405111a18f4baa26206cecd7f5d9530921a33e585c90d0
|
|
| MD5 |
e41117239853851b0edb6cb76229cf9e
|
|
| BLAKE2b-256 |
5b278462b63cb9101d7f04262d028407f2ff7adaca9c63c1298c1c1051055ea8
|
Provenance
The following attestation bundles were made for arachnite-0.11.2-py3-none-any.whl:
Publisher:
publish.yml on memrecolak/arachnite-oss
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
arachnite-0.11.2-py3-none-any.whl -
Subject digest:
a7bc1ab6c7d16b6d40405111a18f4baa26206cecd7f5d9530921a33e585c90d0 - Sigstore transparency entry: 1591266030
- Sigstore integration time:
-
Permalink:
memrecolak/arachnite-oss@8bf274b705ed0fde655f1fd4664817599a1d4c4b -
Branch / Tag:
refs/tags/v0.11.2 - Owner: https://github.com/memrecolak
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8bf274b705ed0fde655f1fd4664817599a1d4c4b -
Trigger Event:
push
-
Statement type: