# Grid-agent architecture foundation The grid agent is a workspace-owned Rust library and small service binary. Its core depends on Tokio for scheduling and bounded channels. Its `live-grid` feature owns the existing `libremetaverse` composition root for grid protocol managers; the default offline graph does not compile live transports. It does not create a second login, UDP, capabilities, inventory, or world client. It contains no CLR/.NET loading, sidecar, subprocess adapter, provider SDK, native ABI, or platform-specific core path. ## Ownership and bounds `AgentService::start` is the sole task-creation point. It validates the complete configuration before allocating channels, calling a backend, or permitting network access. `ServiceHandle` then exclusively owns cancellation, both join handles, the control sender, and observable receiver. | Resource | Owner | Hard/configured bound | Backpressure/termination | | --- | --- | --- | --- | | Grid-event queue | coordinator receives; backend sends | 8,192 / `grid_event_queue` | async send or cancellation | | Control queue | coordinator receives; handle sends | 256 / `control_queue` | async send; closed after stop | | Observable queue | handle receives; coordinator/backend send | 8,192 / `observable_queue` | async send or cancellation | | Backend task | `ServiceHandle.tasks[0]` | exactly one | shared cancellation token, joined first | | Coordinator task | `ServiceHandle.tasks[1]` | exactly one | shared cancellation token, joined second | | Body / message | typed boundary owners | 8 MiB / 64 KiB hard ceilings, with lower configured limits | rejected before enqueue | | Conversation / tool calls | request owner | 256 messages / 64 calls, with lower configured limits | rejected before request | | LLM request slots | shared `LlmClient` semaphore | 256 hard / configured concurrent requests | async acquire or cancellation | | Reasoning/tool session | `ToolLoop` caller | 32 turns / 256 calls hard, with lower configured limits | total timeout, cancellation, or supersession | | Policy tools / approvals / schedules | `PolicyGateway` mutex | 64 tools / 4,096 approval records / 1,024 scheduler grants hard | deny before opaque authorization | | Principal/global resource budget | `PolicyGateway` time window | validated calls, zero L$, upload, inventory, movement, and build ceilings | atomic charge or stable denial | | Authorized avatars | immutable `AgentConfig` set | 1,024 hard ceiling, lower configured limit | malformed, nil, duplicate, and wildcard input rejected | | Configuration / secret file | loader | 64 KiB / 16 KiB | regular non-symlink file only | `BoundedText` and `BoundedVec` make message and collection ceilings part of the type. Dynamic configuration can lower these absolute ceilings but cannot raise them. Backend error text is not forwarded; observations publish a fixed bounded diagnostic. ## State machine and shutdown The explicit service states are `starting -> running <-> paused -> stopping -> stopped`, with `failed` reserved for task failure. The offline backend publishes `BackendReady`, after which the coordinator enters `running`. A shutdown control, direct handle shutdown, backend failure, closed owner queue, or handle drop triggers the same cancellation token. Orderly shutdown first cancels, joins the backend, and then joins the coordinator. Each join has the validated shutdown timeout. A late task is aborted and awaited before return. A partially polled shutdown future only borrows each join handle, so cancelling that future leaves every task in the handle's fixed ownership slots for a retry or final drop. Dropping the handle cancels and aborts all remaining owned tasks, so no task is detached. A feature-enabled live adapter drops its `LibremetaverseClientOwner` last, invoking the existing client ownership shutdown. ## Trust boundaries - JSON configuration and environment text are untrusted. Unknown fields, oversized files, invalid booleans, conflicting modes, non-HTTP(S) URLs, URL fragments, malformed/noncanonical/nil UUIDs, wildcard authorization, multiline secrets, and unsafe limits fail before startup. - `SecretString` and `EndpointUrl` are the only credential-bearing value types. Secrets are never serializable or printable. Endpoint diagnostics replace user information, passwords, and the complete query. - Grid input crosses `GridBackend` only through bounded `GridEvent` values. The `live-grid` feature supplies `LibremetaverseClientOwner`; live implementations must own it and reuse its client and managers. - World changes cross only `WorldMutator::apply`, which always receives the non-forgeable `AuthorizedAction` produced by `PolicyGateway`. Raw calls and caller-created decisions are not accepted. This issue supplies no live mutation implementation. - LLM traffic crosses one exact configured URL through `LlmClient`. Redirects are refused, response bodies are bounded while streaming, bearer secrets are redacted, and provider/model discovery does not exist. Proposed calls cross `ToolExecutor` only after registered-name and schema validation. - Signals and console output belong to the binary. The reusable core relies on no terminal, Unix socket, Unix signal, separator, or fixed platform path. ## Dependency diagram ```text metacrate-grid-agent binary (portable Ctrl-C + config path) | v AgentService -> bounded Tokio channels/tasks -> injected GridBackend | | v v typed config/events/policy boundaries live-grid feature boundary | | +-----------------> libremetaverse-types +--> libremetaverse::GridClient avatar session -> bounded ToolLoop -> exact-endpoint LlmClient | +-> PolicyToolExecutor -> PolicyGateway | +-> AuthorizedToolBackend ``` The package has no build script or direct native dependency. The focused `dependency_policy` test rejects subprocess launch sites, unsafe/native ABI source, build scripts, and unreviewed direct dependency names in this package. The precise LLM compatibility and cancellation contract is documented in [`grid-agent-llm.md`](grid-agent-llm.md). The origin/capability matrix and opaque mutation boundary are documented in [`grid-agent-policy.md`](grid-agent-policy.md).