Context
All Eigenoid code currently lives in a single personal repository (andylow92/SPIRE-A2A-Protocol). This repo contains two components with different lifecycles, tech stacks, and audiences:
- Core: Python package (
eigenoid/), Dockerfile.agent, tests, examples. Consumers: developers integrating agents, CI/CD pipelines, the Docker runtime. - Studio: React/Vite app + FastAPI backend (
studio/). Consumers: agent topology designers, operators deploying from the UI.
With the creation of the eigenoid organization (ADR-0001), this is the natural moment to separate these components into independent repos. Keeping them together has the following problems:
- Coupled versioning: a CSS change in Studio generates a release that includes non-existent changes in Core.
- Unnecessarily broad CI: a frontend PR triggers Python tests and vice versa.
- Unclear ownership: CODEOWNERS cannot be cleanly assigned to each component separately.
- Implicit dependency: Studio appears to depend on Core because they share the same tree, but the dependency is actually operational (Dockerfile.agent +
eigenoidas a pip package inside Docker containers), not a direct import in the backend process.
Decision
We split the monorepo andylow92/SPIRE-A2A-Protocol into two repositories within the eigenoid organization:
eigenoid/core: Python package, Dockerfile.agent, config, docs, tests, examples.eigenoid/studio: React/Vite frontend, FastAPI backend, startup scripts.
Decoupling the Studio backend
The Studio backend (server.py) had a _find_eigenoid_root() function that walked the directory tree upward looking for Dockerfile.agent. This coupling is resolved with:
EIGENOID_CORE_ROOTenvironment variable: the backend checks this first to locate the Core project (Dockerfile.agent and deploy workspace).- Fallback walk-up: if the variable is not set, the legacy behavior of searching upward for
Dockerfile.agentis preserved (useful when both repos are co-located). start.shauto-detects sibling: if../core/Dockerfile.agentexists,EIGENOID_CORE_ROOTis exported automatically.
Studio → Core dependency
Studio does not import eigenoid directly in its Python process. The only references to eigenoid are:
- Code generation (TypeScript → Python strings):
codegen.tsgeneratesfrom eigenoid import ...as text. - Scripts injected into Docker containers: the backend builds Python scripts that run inside containers where
eigenoidis already installed as a pip package viaDockerfile.agent.
Therefore, the dependency is: Studio needs a local copy of eigenoid/core only for deploy (Docker build context). For pure design (canvas + YAML + code preview), Studio is fully self-contained.
Consequences
- Independent versioning: Core and Studio can have their own releases and changelogs.
- Focused CI: each repo runs only its own tests and linters.
- Clear CODEOWNERS: different teams can be assigned to each repo.
- Independent deployment: Studio can be deployed as a static SPA without Core; the deploy backend requires
EIGENOID_CORE_ROOT. - Slightly more complex dev setup: developers who want end-to-end deploy must clone both repos (or use
EIGENOID_CORE_ROOT). Mitigated by auto-detection instart.sh. - Original monorepo becomes an archive:
andylow92/SPIRE-A2A-Protocolcan be archived once the last artifacts are migrated.
Alternatives considered
- Keep monorepo in the org (
eigenoid/eigenoid): zero migration effort, but inherits all the coupling problems described. Does not scale when more components are added (CLI, dashboard, docs site). - Monorepo with workspaces (Turborepo / Nx): solves selective CI but adds extra tooling, does not resolve ownership, and the repo remains a single blob.
- Subtree split (
git subtree): preserves history but creates complexity in PR and merge workflows. The monorepo history is preserved in the original repo; we do not need to replicate it.
References
- ADR-0001 — Create dedicated organization — context for the org migration.
eigenoid/core— Core repo.eigenoid/studio— Studio repo.andylow92/SPIRE-A2A-Protocol— original monorepo.