What this is (and isn't): strange-mca is a vibe-coded conceptual playground, not a production system and not a research result. It exists to play with Michael Levin's Multiscale Competency Architecture and Hofstadter's strange loops using LLM agents, and a large share of the code, tests, and documentation was written with heavy assistance from Claude. Treat the architecture as exploratory, the metrics as instruments for playing, and every claim in the docs as a hypothesis — nothing here has been validated beyond small, informal experiments.
A multiagent system that models a Multiscale Competency Architecture (MCA) with Strange Loop self-reflection. LLM agents are arranged in a hierarchy where each agent responds independently from a unique perspective, communicates laterally with peers, and iterates in rounds until the root's output converges. Higher-order behavior emerges from local interaction, not top-down assignment.
The MCA concept comes from Michael Levin's work on how biological systems exhibit competence across multiple scales — from cells to organisms to social groups. This project uses LLMs as the information-processing nodes in a simplified software model of that idea. The Strange Loop component adds configurable self-reflection at the root node during finalization.
Each run produces a final_state.json and mca_report.json in the output directory for inspecting agent behavior.
The architecture's central bet — that coherent collective behavior can emerge from purely local agent interaction — turns out to be a question with actual theory behind it. docs/topology-learnings.md connects strange-mca to statistical-mechanics results on self-organisation (Sacco, Sakthivadivel & Levin 2026) and to Herbert Simon's The Sciences of the Artificial: the interaction topology alone determines which collective phases are possible, sibling groups with lateral visibility are the theory's "cliques," and the target behavior (internally coherent groups holding genuinely different positions) is a predicted stable phase with identifiable failure modes on either side. The phase metrics in mca_report.json, the --lateral_pressure knob, and scripts/topology_experiment.py exist to test those predictions; open jumping-off points are tracked as GitHub issues.
The system uses a single flat LangGraph StateGraph with round-based bottom-up processing:
init → leaf_respond → leaf_lateral → [observe_L{n} → lateral_L{n}]* → observe_root → signal_down → check_convergence → [loop | finalize] → END
- Specialist (leaf): Responds to the full task from a unique perspective (analytical, creative, critical, etc.)
- Coordinator (internal): Observes children's outputs and identifies emergent patterns
- Integrator (root): Produces holistic synthesis from coordinator/specialist outputs
- Leaf Respond: Each leaf generates an independent response from its assigned perspective
- Leaf Lateral: Leaves see siblings' responses and revise while maintaining their viewpoint
- Internal Observe/Lateral: Per internal level (bottom to top), coordinators observe children and communicate laterally with peers
- Root Observe: Root synthesizes children's outputs into a unified response
- Signal Down (optional): Non-leaf agents send brief nudges to children highlighting gaps or tensions
- Convergence Check: Jaccard similarity on root output across rounds; loop or finalize
The strange loop self-reflection occurs at finalization, after convergence.
- Hierarchical Agent Structure: Configurable tree of agents with customizable depth and branching factor
- Emergent Bottom-Up Processing: Agents respond independently; coherence emerges from local interactions rather than top-down decomposition
- Lateral Peer Communication: Agents at the same level see siblings' responses and revise their own, maintaining their unique viewpoint
- Round-Based Convergence: The system iterates until the root's output stabilizes (Jaccard similarity threshold) or max rounds reached
- Downward Signals: Parent agents send brief nudges to children highlighting gaps or tensions (configurable)
- Multiple Perspectives: Leaf agents are assigned from a pool of 8 default perspectives — analytical, creative, critical, practical, theoretical, empirical, ethical, systemic — or custom perspectives via CLI/API
- Strange Loop Refinement: Optional self-critique and refinement of the final response at the root
- Lateral Pressure Control:
--lateral_pressure(maintain / balanced / integrate) sets how strongly lateral prompts push agents toward peer agreement — the coupling-strength dial from the theory - Visualization Tools: Generate visual representations of the agent tree and execution graph
- Observability Reports: JSON reports (
mca_report.json) with per-round agent data, convergence trajectory, LLM call counts, lateral revision rates, and phase metrics (sibling-group similarity, cross-group similarity, agent stability, a round-1 no-interaction baseline, and a phase classification: converged_hierarchical / converged_collapsed / stuck / oscillating, plus converged_unmeasured for topologies without sibling groups). Metrics use Jaccard by default or, with--similarity_method embedding, text embeddings that see through paraphrase (report-side only; the convergence loop stays Jaccard)
- Python 3.9+
- Poetry for dependency management
-
Clone the repository:
git clone https://github.com/josecodes/strange-mca.git cd strange-mca -
Install dependencies using Poetry:
poetry install
-
Create a
.envfile in the project root with your OpenAI API key:OPENAI_API_KEY=your_api_key_hereOptionally, route the agents' chat calls through any OpenAI-compatible gateway (a LiteLLM proxy serving local or third-party models) by setting
MCA_CHAT_BASE_URLandMCA_CHAT_API_KEYand passing the gateway's model name via--model. These are deliberately separate from theOPENAI_*variables so embeddings keep their default routing.
You can run the strange-mca system using the command-line interface:
poetry run python -m src.strange_mca.main --task "Your task here" --child_per_parent 3 --depth 2 --model "gpt-4o-mini"| Argument | Default | Description |
|---|---|---|
--task |
"Explain the concept of multi-agent systems" |
The task to perform |
--child_per_parent |
3 |
Number of children per parent node |
--depth |
2 |
Number of levels in the tree |
--model |
"gpt-4o-mini" |
LLM model to use |
--max_rounds |
3 |
Maximum number of rounds for convergence |
--convergence_threshold |
0.85 |
Jaccard similarity threshold for convergence (0-1) |
--enable_downward_signals |
on | Enable parent-to-child signals |
--no_downward_signals |
— | Disable parent-to-child signals |
--perspectives |
8 defaults | Custom perspectives for leaf agents (space-separated) |
--lateral_pressure |
"balanced" |
How strongly lateral prompts push toward peer agreement (maintain, balanced, integrate) |
--similarity_method |
"jaccard" |
Similarity for the report's phase metrics (jaccard, embedding); report-side only |
--strange_loop_count |
0 |
Number of strange loop iterations to perform |
--domain_specific_instructions |
"" |
Domain-specific instructions for the strange loop prompt |
--log_level |
"info" |
Logging level (debug, info, warning, error, critical) |
--local-logs-only |
off | Show only logs from strange_mca, suppress dependency logs |
--viz |
off | Generate visualizations of the agent tree and execution graph |
--dry_run |
off | Don't run the system, just show the configuration |
--print_tree |
off | Print the agent tree structure |
--print_details |
off | Print full state details after execution |
You can also use strange-mca programmatically in your Python code:
from src.strange_mca.run_strange_mca import run_strange_mca
result = run_strange_mca(
task="Explain the concept of multi-agent systems",
child_per_parent=2,
depth=2,
model="gpt-4o-mini",
max_rounds=3,
convergence_threshold=0.85,
enable_downward_signals=True,
perspectives=None, # uses 8 defaults
lateral_pressure="balanced", # or "maintain" / "integrate"
similarity_method="jaccard", # or "embedding" (report-side only)
strange_loop_count=1,
domain_specific_instructions="Focus on practical applications",
)
print(result["final_response"])The return value is a dict containing final_response, converged, convergence_scores, current_round, agent_history, and strange_loops.
For structured observability data, use build_mca_report():
from src.strange_mca.run_strange_mca import build_mca_report
report = build_mca_report(result, task="...", config={...})
# report contains: task, config, rounds (per-agent data), convergence, summary_metrics, final_responsesrc/strange_mca/: Core implementationmain.py: CLI entry point with MCA parametersrun_strange_mca.py: Programmatic API andbuild_mca_report()observabilitygraph.py: FlatStateGraph,MCAState,create_execution_graph(),run_execution_graph()agents.py:AgentConfig(topology-aware),Agent(wraps ChatOpenAI),build_agent_tree(),PERSPECTIVESprompts.py: MCA prompt functions (competency, initial response, lateral, observation, signal, strange loop)tree_helpers.py: Pure functions for node naming, parent/child/sibling relationships, tree traversalconvergence.py: Jaccard token similarity for convergence detection, plus phase metrics (group similarity, embedding similarity, phase classification)visualization.py: Agent tree and execution graph visualizationlogging_utils.py: Detailed logging utilities
tests/: Test suite (179 unit tests + 5 live integration tests)test_agents.py,test_graph.py,test_prompts.py,test_tree_helpers.py,test_convergence.py: Unit tests for core modulestest_main.py,test_run_strange_mca.py,test_visualization.py: Integration teststest_emergent_properties.py: Automated tests for emergent behavior propertiestest_live_integration.py: Live tests requiringOPENAI_API_KEY(marked@pytest.mark.live)
docs/: Design documents and RFCs, theory notes (topology-learnings.md), the empirical record (experiment-log.md), and the next-phase handoff (software-factory-handoff.md)scripts/: Linting and development scripts, plustopology_experiment.py(compare topologies and lateral-pressure settings via phase metrics) andrescore_report.py(re-analyze saved runs under another similarity method)output/: Generated outputs, reports, and visualizations
Run all unit tests:
poetry run pytestRun a single test file or test by name:
poetry run pytest tests/test_agents.py
poetry run pytest -k "test_name"Run live integration tests (requires OPENAI_API_KEY):
poetry run pytest -m live -vLive tests hit the OpenAI API and verify end-to-end behavior including lateral communication, convergence trajectories, downward signals, and report output.
This system mainly serves as a conceptual playground to model MCA and Strange Loop in a multiagent system; the focus is on exploring these concepts, not building a production system.
See GitHub Issues for planned improvements, organized by label:
mca- Multiscale Competency Architecture enhancementsstrange-loop- Strange Loop self-reflection improvementstech- Technical improvements and maintenance
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Implement your changes
- Run tests:
poetry run pytest - Run linting:
./scripts/lint.sh - Submit a pull request
This project uses Ruff and Black for code linting and formatting:
# Run both Ruff and Black
./scripts/lint.sh
# Auto-fix issues
./scripts/lint.sh --fixSee scripts/README.md for more details on the linting scripts.
This project is licensed under the MIT License - see the LICENSE file for details.
- This project uses LangGraph for graph-based execution
- Inspired by Michael Levin's work on Multiscale Competency Architectures and Douglas Hofstadter's Strange Loop