Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ Agentbox is in active development:
- the runtime is sovereign/profile-based
- tmux with fish shell provides the multi-tab terminal experience (MAD-style layout)
- profile isolation replaces Linux pseudo-user isolation
- **pluggable adapters** replace hardcoded durable-state services (see [ADR-005](docs/adr/ADR-005-pluggable-adapter-architecture.md)): beads, pods, memory, events, orchestrator — each resolves to `local-*`, `external`, or `off`
- **pluggable adapters** replace hardcoded durable-state services (see [ADR-005](docs/reference/adr/ADR-005-pluggable-adapter-architecture.md)): beads, pods, memory, events, orchestrator — each resolves to `local-*`, `external`, or `off`
- standalone-or-federated: `federation.mode = "standalone"` ships a complete product with local fallbacks; `federation.mode = "client"` federates with a host container mesh through adapter endpoints
- embedded RuVector is a per-session retrieval cache, not a durable source of truth
- **MCP memory is mandatory ruvector-postgres** ([ADR-015](docs/reference/adr/ADR-015-mcp-ruvector-mandate.md)): the `ruvector-mcp.cjs` server fails closed if PostgreSQL is unreachable — no silent sql.js fallback. The entrypoint generates `.mcp.json` at boot and auto-installs the `pg` module to the workspace bind mount.

Full product spec: [PRD-001](docs/prd/PRD-001-capabilities-and-adapters.md). Adapter contract + SLOs + observability: [ADR-005](docs/adr/ADR-005-pluggable-adapter-architecture.md).
Full product spec: [PRD-001](docs/reference/prd/PRD-001-capabilities-and-adapters.md). Adapter contract + SLOs + observability: [ADR-005](docs/reference/adr/ADR-005-pluggable-adapter-architecture.md).

## Canonical Runtime Files

Expand All @@ -40,7 +40,7 @@ Content addressing: `sha256-12-<12 hex chars>` (same convention both sides).

Minting: all URNs are minted via `management-api/lib/uris.js`. All durable identifiers MUST be minted through `uris.js`. Ad-hoc `format!()` or template-literal URNs are prohibited.

Resolvability: best-effort via `/v1/uri/<urn>` (307/404/410). Canonical ref: [ADR-013](docs/adr/ADR-013-canonical-uri-grammar.md).
Resolvability: best-effort via `/v1/uri/<urn>` (307/404/410). Canonical ref: [ADR-013](docs/reference/adr/ADR-013-canonical-uri-grammar.md).

Parallel namespace: the host project's Rust substrate uses `urn:visionclaw:<kind>:<hex-pubkey>:<local>` (6 kinds: `concept`, `kg`, `bead`, `execution`, `group`) minted in `src/uri/`. Owner-scoped kinds use 64-char hex pubkey as scope (not bech32 npub). The BC20 anti-corruption layer maps between the two namespaces at the federation boundary.

Expand Down Expand Up @@ -86,6 +86,6 @@ These exist for historical context or partial compatibility and should not be tr
When architecture changes, update these together:

- [`README.md`](README.md)
- [`docs/guides/quick-start.md`](docs/guides/quick-start.md)
- [`docs/user/quickstart.md`](docs/user/quickstart.md)
- [`CLAUDE.md`](CLAUDE.md)
- relevant ADRs in `docs/adr/`
- relevant ADRs in `docs/reference/adr/`
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ Deeper reading:
- [Identity and tracing mesh](docs/developer/identity-mesh.md)
- [Adapter pattern](docs/developer/adapters.md)
- [Sovereign mesh](docs/developer/sovereign-mesh.md)
- [Ecosystem integration](docs/developer/ecosystem.md)
- [Testing](docs/developer/testing.md)

### Canonical specs
Expand Down Expand Up @@ -315,6 +316,37 @@ Deeper reading:
3. Prefer manifest-gated additions over ad hoc runtime mutation.
4. Treat hardening, probe semantics, URI grammar, and linked-data surfaces as architectural changes — propose them via an ADR.

## Ecosystem

Agentbox is one of five federated repositories in the DreamLab open-source ecosystem, connected via `did:nostr` identity and a private Nostr relay mesh.

```mermaid
graph LR
SPR["solid-pod-rs<br/><i>Foundation</i>"] -->|dep| NRF["nostr-rust-forum<br/><i>Forum Kit</i>"]
SPR -->|dep| AB["agentbox<br/><i>Agent Container</i>"]
SPR -->|dep| VC["VisionClaw<br/><i>Integration Substrate</i>"]
NRF -->|kit| DW["dreamlab-ai-website<br/><i>Deployment</i>"]
AB <-.->|"relay mesh"| VC
AB <-.->|"relay mesh"| NRF
VC <-.->|"relay mesh"| NRF

style AB fill:#4a9eff,stroke:#2563eb,color:#fff
```

| Repository | Role | Key Technology |
|---|---|---|
| [solid-pod-rs](https://github.com/DreamLab-AI/solid-pod-rs) | Foundation library | Solid Protocol, DID:Nostr, WAC |
| [nostr-rust-forum](https://github.com/DreamLab-AI/nostr-rust-forum) | Forum kit | 11 `nostr-bbs-*` Rust crates, CF Workers |
| **[agentbox](https://github.com/DreamLab-AI/agentbox)** | **Agent container** | **Nix, nostr-rs-relay, mesh peer** |
| [VisionClaw](https://github.com/DreamLab-AI/VisionClaw) | Integration substrate | Knowledge graph, GPU physics, XR |
| [dreamlab-ai-website](https://github.com/DreamLab-AI/dreamlab-ai-website) | Branded deployment | React SPA, WASM forum, `forum-config/` |

All five share `did:nostr:<hex-pubkey>` as the universal identity primitive and communicate via IS-Envelope messages over a private Nostr relay mesh.

Deeper reading: [Ecosystem integration guide](docs/developer/ecosystem.md)

---

## License

Core project: [AGPL-3.0](LICENSE).
Expand Down
8 changes: 6 additions & 2 deletions config/entrypoint-unified.sh
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,8 @@ if [ -f "$_RUVECTOR_MCP" ]; then
chown -R 1000:1000 "$_PG_PREFIX" 2>/dev/null || true
fi
# Write canonical .mcp.json (idempotent — only if it doesn't already point to ruvector-mcp)
: "${XINFERENCE_ENDPOINT:=http://xinference:9997}"
: "${EMBEDDING_MODEL:=bge-small-en-v1.5}"
if [ ! -f "$_MCP_JSON" ] || ! grep -q "ruvector-mcp" "$_MCP_JSON" 2>/dev/null; then
cat > "$_MCP_JSON" <<MCPEOF
{
Expand All @@ -426,14 +428,16 @@ if [ -f "$_RUVECTOR_MCP" ]; then
"type": "stdio",
"env": {
"RUVECTOR_PG_CONNINFO": "host=ruvector-postgres port=5432 dbname=ruvector user=ruvector password=$RUVECTOR_PG_PASSWORD",
"NODE_PATH": "$_PG_PREFIX/node_modules"
"NODE_PATH": "$_PG_PREFIX/node_modules",
"XINFERENCE_ENDPOINT": "$XINFERENCE_ENDPOINT",
"EMBEDDING_MODEL": "$EMBEDDING_MODEL"
}
}
}
}
MCPEOF
chown 1000:1000 "$_MCP_JSON" 2>/dev/null || true
echo " [mcp] Wrote $_MCP_JSON → ruvector-mcp.cjs (ruvector-postgres backend)"
echo " [mcp] Wrote $_MCP_JSON → ruvector-mcp.cjs (ruvector-postgres + xinference)"
fi
fi

Expand Down
3 changes: 3 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ You are adding a feature, implementing an adapter, or investigating a regression
| [Adapter pattern](developer/adapters.md) | Five slots × three classes; how to write a new impl |
| [Sovereign mesh](developer/sovereign-mesh.md) | Nostr client + NIP-98 auth + relay pool internals |
| [Linked-Data middleware](developer/linked-data.md) | Encoder + ContextResolver + LION linter + JCS — surface authoring guide |
| [Ecosystem integration](developer/ecosystem.md) | Agentbox's role in the five-substrate DreamLab federation mesh |
| [Skills upgrade path](developer/skills-upgrade.md) | Migrating from `path:./skills` to a standalone repo |

| Tooling | |
Expand Down Expand Up @@ -101,6 +102,8 @@ These are the authoritative sources of truth. Anything in `user/` or `developer/
| ADR-011 | [Consultation MCP servers](reference/adr/ADR-011-consultation-mcps.md) | Accepted | Coordinator + named-consultant pattern; rejects transparent API rewriting as the meta-router |
| ADR-012 | [JSON-LD 1.1 as the federation interchange grammar](reference/adr/ADR-012-jsonld-federation-grammar.md) | Accepted | JSON-LD as the third cross-cutting middleware after observability and privacy; LION subset for hand-authored docs |
| ADR-013 | [Canonical URI grammar and resolver](reference/adr/ADR-013-canonical-uri-grammar.md) | Accepted | `did:nostr:<pubkey>` + `urn:agentbox:<kind>:[<scope>:]<local>`; uniqueness unconditional, resolvability best-effort; `/v1/uri/<urn>` resolver |
| ADR-014 | [Bi-directional graph-state ingress](reference/adr/ADR-014-bidirectional-graph-state-ingress.md) | Proposed | Bi-directional graph-state ingress for agent reaction |
| ADR-015 | [MCP ruvector-postgres mandate](reference/adr/ADR-015-mcp-ruvector-mandate.md) | Accepted | `ruvector-mcp.cjs` fails closed if PostgreSQL is unreachable; no silent sql.js fallback |

### Product requirements (PRD)

Expand Down
85 changes: 85 additions & 0 deletions docs/developer/ecosystem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Ecosystem integration

Agentbox is one of five federated repositories in the DreamLab open-source ecosystem. This document explains how agentbox participates in the mesh and how its boundaries interact with the other substrates.

## Five-substrate landscape

| Repository | Role | Relationship to agentbox |
|---|---|---|
| [solid-pod-rs](https://github.com/DreamLab-AI/solid-pod-rs) | Foundation library | Consumed as the embedded Solid pod server (ADR-010) |
| [nostr-rust-forum](https://github.com/DreamLab-AI/nostr-rust-forum) | Forum kit | Peer on the relay mesh; receives IS-Envelope messages |
| **[agentbox](https://github.com/DreamLab-AI/agentbox)** | **Agent container** | **This repository** |
| [VisionClaw](https://github.com/DreamLab-AI/VisionClaw) | Integration substrate | Host project when used as a submodule; peer on the relay mesh |
| [dreamlab-ai-website](https://github.com/DreamLab-AI/dreamlab-ai-website) | Branded deployment | Downstream consumer of the forum kit; no direct dependency on agentbox |

## Mesh participation

Agentbox participates as a mesh peer via its built-in `nostr-rs-relay` (ADR-009). When `federation.mode = "client"` is set in `agentbox.toml`, the relay connects to the private relay mesh and exchanges NIP-42-authenticated messages with other substrates.

The shared identity primitive across all five repositories is `did:nostr:<hex-pubkey>`, derived from a BIP-340 secp256k1 keypair generated at bootstrap. Cross-system messages use the IS-Envelope v1 contract (7 envelope kinds, JCS-canonicalised, NIP-59 gift-wrapped on the wire).

## Federation message flow

```mermaid
sequenceDiagram
participant AB as agentbox<br/>did:nostr:hex-a
participant Relay as Private Nostr<br/>relay mesh
participant VC as Host project<br/>did:nostr:hex-b
participant NRF as Forum instance<br/>did:nostr:hex-c

AB->>AB: Bootstrap keypair, mint did:nostr:hex-a
AB->>Relay: NIP-42 AUTH (hex-a)
Relay-->>AB: OK

Note over AB,VC: Bi-directional graph-state ingress (ADR-014)
VC->>Relay: IS-Envelope (knowledge_link) NIP-59
Relay->>AB: Deliver to hex-a subscription
AB->>AB: Pod-inbox bridge writes to Solid pod
AB->>AB: Adapter dispatch (privacy filter, JSON-LD encode)

Note over AB,NRF: Agent-to-forum communication
AB->>Relay: IS-Envelope (chat) NIP-59
Relay->>NRF: Deliver to hex-c subscription
NRF-->>Relay: IS-Envelope (tool_result) NIP-59
Relay-->>AB: Deliver reply
```

## Dependency on solid-pod-rs

Agentbox consumes `solid-pod-rs` as its first-class Solid Protocol 0.11 server (ADR-010). The pod provides durable storage with WAC 2.0 access control, `did:nostr` identity binding, atomic-rename writes, and quota enforcement. The pod-inbox bridge (ADR-009) routes inbound Nostr relay messages into the pod's LDP inbox as AS2 LDN notifications.

## Integration contract with the host project

When agentbox is used as a git submodule inside a host project, the integration boundary is defined by:

- **ADR-014** (this repo): Bi-directional graph-state ingress for agent reaction
- **ADR-059** (host project): The corresponding integration contract on the host side

The host project is always referenced by role ("host project", "integrator", "external orchestrator") rather than by name. This is a deliberate design decision: agentbox is a standalone product that can be consumed by any host, and its documentation must not couple to a specific integrator.

## URI namespace boundary

Two parallel URI namespaces exist by design:

- `urn:agentbox:<kind>:[<scope>:]<local>` -- 18 kinds, minted in `management-api/lib/uris.js`
- `urn:visionclaw:<kind>:<hex-pubkey>:<local>` -- 6 kinds, minted in the host project's `src/uri/`

Both share `did:nostr:<hex-pubkey>` identity and `sha256-12-<12 hex chars>` content addressing. The BC20 anti-corruption layer maps between the two namespaces at the federation boundary.

## Standalone vs federated

Agentbox ships as a complete product in both modes:

- `federation.mode = "standalone"` -- local SQLite + JSONL adapters, no relay mesh, fully self-contained
- `federation.mode = "client"` -- connects to the relay mesh, federates with other substrates via adapter endpoints

The adapter contract (ADR-005) guarantees that every feature works in both modes. Contract tests in `tests/contract/` must pass for all three implementation classes per slot.

## Further reading

- [Sovereign mesh internals](sovereign-mesh.md)
- [Adapter pattern](adapters.md)
- [Identity and tracing mesh](identity-mesh.md)
- [ADR-009 -- Embedded Nostr relay](../reference/adr/ADR-009-embedded-nostr-relay.md)
- [ADR-010 -- solid-pod-rs adoption](../reference/adr/ADR-010-rust-solid-pod-adoption.md)
- [ADR-014 -- Bi-directional graph-state ingress](../reference/adr/ADR-014-bidirectional-graph-state-ingress.md)
2 changes: 2 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1669,6 +1669,8 @@ ${agentboxPorts}
- AGENTBOX_METRICS_PORT=${metricsPort}
- AGENTBOX_OTLP_ENDPOINT=${observCfg.otlp_endpoint or ""}
- AGENTBOX_LOG_LEVEL=${observCfg.log_level or "info"}
- XINFERENCE_ENDPOINT=''${XINFERENCE_ENDPOINT:-http://xinference:9997}
- EMBEDDING_MODEL=''${EMBEDDING_MODEL:-bge-small-en-v1.5}
# Baseline: supervisord runs as PID 1 root, with per-program `user=devuser`
# drops on every long-running service. Root is required at boot for
# tmpfs subdir creation, sudoers wrapper provisioning (chown 0:0 +
Expand Down
10 changes: 8 additions & 2 deletions management-api/middleware/linked-data/surfaces/s04-did.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/

const DID_CONTEXT = 'https://www.w3.org/ns/did/v1';
const SECP_CONTEXT = 'https://w3id.org/security/suites/secp256k1-2019/v1';
const AGBX_CONTEXT = 'https://agentbox.dreamlab-ai.systems/ns/v1#';

module.exports = {
Expand Down Expand Up @@ -65,16 +66,21 @@ module.exports = {

const verificationMethods = [];
if (pubkeyHex) {
// ADR-074 D1 + ADR-077 P3 + V3 C4 finding: cross-system DID
// canonicalisation requires SchnorrSecp256k1VerificationKey2019 — the
// only published W3C suite for secp256k1 Schnorr verification keys.
// SchnorrSecp256k1VerificationKey2025 was a spec-drift fabrication that
// no DID resolver or W3C VC verifier accepts.
verificationMethods.push({
id: `${did}#schnorr-pubkey`,
type: 'SchnorrSecp256k1VerificationKey2025',
type: 'SchnorrSecp256k1VerificationKey2019',
controller: did,
publicKeyHex: pubkeyHex,
});
}

const doc = {
'@context': [DID_CONTEXT, AGBX_CONTEXT],
'@context': [DID_CONTEXT, SECP_CONTEXT, AGBX_CONTEXT],
id: did,
verificationMethod: verificationMethods,
service: services,
Expand Down
Loading
Loading