Catalog PyPI
PACKAGE EXPLORERView in registry

agience-ember

PyPI

Ember — an observer unit: the Agience local leaf/cache, two-way, holds its own shards and runs disconnected. Import name is `ember`.

agiencecacheemberleafmeshobserverofflineshards
Versions collected1
Direct dependencies12From release 0.2.0
Last observed21 Oct, 09:05 UTC

README

Version 0.2.0 documentation

Agience Ember

PyPI Python License CI Sponsor

An observer unit — the local leaf.

Ember runs on your machine, holds its own shards, answers from them, and reaches the mesh only on a miss. It is two-way: it serves your local services to the network, and the network to your local services.

Install

pip install agience-ember             # the leaf
pip install 'agience-ember[optics]'   # ...and the instrument that measures

Requires Python 3.11 or newer.

ember status                       # what this leaf holds, and whether it is seeded
ember ask "..."                    # answer from local shards, citing what it grounded on
ember ingest --anchors <path> ...  # observe and describe into the durable store, then index
ember reindex --anchors <path>     # rebuild the derived index from the store alone
ember serve                        # an OpenAI-compatible /v1 endpoint on 127.0.0.1:8091

--anchors is a path to the canonical AnchorSet artifact and is required on both ingest and reindex. An anchor id is content-addressed over (label, model_id, embedding), so anchors are provisioned rather than derived locally: a home-made set would route into cells no peer shares.

First light

A leaf runs disconnected and is initialised from outside, once. Two things have to arrive:

  1. The canonical AnchorSet — without it there is no routing.
  2. The authority's public key — without it a cached shard cannot be verified, and an unverified shard is a rumour rather than a cache.

seed(anchors, authority_pub) is an explicit call, and boot is purely local — tested by making socket.connect raise — so startup is fast, offline, and cannot hang on a dead network.

Until it is seeded a leaf is uninitialised, which is its own condition with its own remedy. An empty leaf answers "I don't hold that"; an uninitialised one cannot route, so status says which it is.

Cache with a socket

Every shard is content-addressed and authority-signed, so a cached shard is exactly as trustworthy as the origin's, verified independently of who served it. Replication is blind: Ember can hold ciphertext it cannot read, decrypting only what the holder has grants for. Caching decisions and authorization decisions are therefore separable — a neighbourhood can be pre-warmed while reads stay bounded by grants.

cache concernmechanism
invalidationmonotonic version per region; gossip surfaces "newer exists"
working set / evictionroute_query_regions() — what answers a query is computable
refill sourcethe gossip directory ranks providers freshest → most-coherent → densest
integrityMerkle content_root plus an Ed25519 authority signature

A region id is a path of artifact identities — {principal}/{collection_id}/{anchor_id} — which is why two nodes that never met agree on what a cell is called. Ember's local collection is an artifact it authors, with id uuid5(principal), so one person's laptop and desktop derive the same id and can sync directly.

Reasoning over evidence

Reasoning is lightweight. Knowledge lives in artifacts and is retrieved.

The engine's signature is the whole contract:

answer(query: str, evidence: Sequence[Evidence]) -> Answer

evidence is its only knowledge input, so a wrong answer can only come from wrong evidence — which is inspectable, attributable and fixable.

Composing prose is a persona act, so ember.runtime.engine.build() raises NoAnswerer and an answerer arrives by injection: Ember(..., engine=<answerer>). Left unwired, ask() reports that it has no answer. EMBER_ENGINE is still read into settings, and selects nothing.

The local projection

A leaf embeds queries locally or disconnected operation is a fiction — but region ids are derived from the canonical anchors, so a leaf that embedded with its own model would mint its own ids and name cells nobody else uses. Its shards would be unshareable, silently, because routing would still appear to work.

So Ember caches the canonical AnchorSet and projects into it with a cross-walk: same dimension → orthogonal Procrustes, cross dimension → rectangular least squares. A 384-dim leaf routes against a 1024-dim canonical space and lands on the same region ids.

The fit is offline. An anchor carries both its label and its canonical embedding, so Ember embeds the cached labels with its own model, pairs them against the canonical vectors already present, and solves. The network is called only to learn about new anchors. "Small while disconnected, upgrade during sync" is then: refresh the AnchorSet and refit.

The cross-walk is itself an artifact — derived data with provenance and a measured error_bound, deterministic given (embedder, AnchorSet), so every leaf on the same embedder computes the identical matrix. Fit once, publish, adopt. Its id includes an anchorset fingerprint, because a walk fitted against older anchors still projects and still routes — into yesterday's cells. The fingerprint turns that into an ordinary cache miss.

Semantic retrieval is the computed ontology coordinate: an exact Jiang–Conrath vector derived from our own WordNet information content. HashEmbedder (ember.embed) is the deterministic plumbing exerciser and is not a retrieval path.

The instrument

ember/optics.py is the one module here that imports the instrument package, enforced by an AST test (tests/test_one_instrument.py). It pins INSTRUMENT_REQUIRED = "0.2" and matches major.minor exactly with patch floating, so a version skew fails at import rather than inside a reading.

The dependency is the [optics] extra: a node that carries frames installs the base, a node that measures them installs [optics], and prism.instrument reports an absent measurement at the point of measurement.

Importing ember registers the instrument as the process-default through a factory, so import ember loads numpy and the instrument only at the first measurement. The registration is process-global, which is why an import ember line elsewhere is a host declaration and carries # noqa: F401 with a header saying so.

Configuration

EMBER_CACHE_DIR · EMBER_PRINCIPAL · EMBER_COLLECTION_ID · EMBER_ENGINE · EMBER_EMBED_MODEL · EMBER_CLOUD_URI · EMBER_NPROBE. The cache defaults to %LOCALAPPDATA%\agience-ember on Windows and $XDG_CACHE_HOME/agience-ember elsewhere.

Layout

modulerole
runtime/boot.pythe assembly — Ember.boot() · .seed() · .connect() · .ask() · .remember() · .revise() · .status()
runtime/read_path.pyquery → route → hit? answer local : miss → refill → answer
runtime/relay.pythe two-way channel: Channel · Disconnected · MeshChannel, transport injected
runtime/engine.pythe reasoning half; the answerer is injected
runtime/seams.pythe host seam table, bound at package scope so any process holding ember is a host
config.pyenv-driven settings
optics.pythe instrument — the one module importing its package
genesis.pythe operator corpus and the provenance rungs
ontology/activation (spreading activation over the taxonomy), match (the propagation kernel and its measured constants), information, corpus_stats
signal/projection · forgetting · pooling · signal · state
corpus/ingest, the stage-0 sources and full-text search
consolidate/colimit and diagram
surface/serve (the inward HTTP direction), console, stats
embed.pyEmbedder, HashEmbedder and the Aligner that fits the cross-walk
cli.pythe ember console script

Status

Scaffold. The read path is real and tested disconnected, the cache survives a restart, and the outward relay refill — miss → pull → verify → answer — is live over an injected transport, so it is tested with no socket. The inward serve() direction is a seam.

To work on Ember itself, see CONTRIBUTING.md, which lists what the suite needs.

Security issues: email connect@agience.ai rather than opening a public issue.

Dual-licensed — see LICENSE, COMMERCIAL_LICENSE.md, NOTICE and CLA.md.

Declaration of generative AI use

The author used Anthropic's Claude Opus (versions 4.8, 5, and 5.5) in the preparation of this work. Its contribution was to write code, and to generate and validate content. The ideas, the construction and the claims are the author's. No other generative AI tool was used. The author reviewed and edited all output and takes full responsibility for the content of this publication.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.2.010 Oct 202612

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
agience/agience-ember

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 21 Oct, 09:05 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:a4202576baa17bba33162bba13bdc71810e9cb6c94f64fe00084823fd83c95dc