fleetd

Native runtime adapters

How adapters run Codex and Pi, confirm delivery and handle owner questions.

Source reference: services/crossfire/docs/runtime.md at 52bf0279

fleetd owns native processes through runtime adapters. crossfire owns coordination, authorization and observations; it never launches or kills agents.

The adapters support Codex and Earendil Pi. Claude configuration is rejected. Adapters use runtime protocols rather than reading terminal text for control.

Settings and histories#

A role definition supplies native defaults. Instance top-level settings override them; nested tables replace whole values. The adapter resolves and validates the same effective settings for inspection, startup, resume, recovery and reset. Unavailable model/effort combinations fail before startup; no substitution occurs.

Codex requires stock 0.158.0+ and the actual native capabilities used by this release, including developer-item injection. A version number alone is not proof. Selected model/effort support is checked through native config/model APIs. Managed defaults are danger-full-access and on-request approval unless explicitly configured. A supported explicit bypass is a deliberate owner choice.

Each activation atomically refreshes provider authentication from the current authorized host source. It does not import the setup assistant’s history or silently switch a running engine’s account. Invalid private login files fail; an absent source removes stale file login.

Instructions are inserted as native developer or custom entries without making a model call. Unchanged instructions do not append duplicates. Changed AGENTS.md, skill or administrator text uses the same producer on the next eligible activation.

Message delivery and interruption#

The listener filters native Matrix events using current account, room, wake and controller authority. Input identifies the receiving agent and owner, sender, room, event and timestamp. Missing metadata is marked unknown.

Eligible native user mentions interrupt the exact captured active turn before replacement input. Humans and agents have the same accepted-source rule. Display names, quoted text, edits, old snapshots, self and internal notices do not become controls. Shared context targets the shared history; per-room mode targets only that room.

Steering bypasses ordinary collection/work queues. Cold startup still has a finite native-start capacity; non-admission is visible and does not consume unread input. The owner DM records receipt, interruption/already-idle and exact input acceptance with measured timestamps. A delivered input receipt is not completed model work. Cancellation does not roll back prior tool effects.

Unconfirmed delivery#

The adapter journals exact input identity/text and history boundary before sending. Only an exact native receipt advances unread state. RPC success or a client correlation ID alone is insufficient. Confirmed input survives restart without replay; pending work is resolved before a new reminder/message.

A restarted process has no old running turn. If delivery of the previous message cannot be confirmed from history, that message is saved to a private file. A new restart instruction points to it. The instruction says delivery was unknown and asks the model to inspect prior effects before continuing. It does not claim exactly-once external execution.

Invalid/corrupt identity journals are permanent conflicts, not unlimited restart conditions. Do not delete them to force a new context.

Owner output and decisions#

Visible non-thinking native output goes only to the verified private owner DM. Reasoning traces, hidden protocol credentials and secret answers are excluded. Shared-room replies require an intentional messaging-tool call with an explicit destination. Terminal output never infers a public audience.

The owner is trusted to see this transcript, including shared-context information from rooms they have not joined. This is not room confidentiality isolation. Machine-specific paths may appear in that owner DM; agents are instructed not to disclose them to other audiences. That instruction is not a guaranteed scrubber.

Native permission/questions use one decision port. Only the current owner can answer the exact pending request. A choice URL is read-only; an authenticated, same-origin/CSRF-protected submission is required. Silence is never consent. Multiple questions require one complete answer set.

Pending, Answered, Responded, Cancelled and Expired have distinct meanings. Responded records the original native socket-write completion, not proof of subsequent model execution. Request-clear notifications can be cancellation. Unsupported shell/TUI prompts are not guessed from prose.

Activity, sleep and failure#

Native state distinguishes idle, working, waiting, sleeping, waking, failed and unavailable. Initialization stays waking until receipt/continuation readiness. Unknown activity prevents automatic sleep instead of inventing idle.

Idle timeout defaults to thirty minutes. Busy contexts, questions, pending input, startup/cleanup and uncertain receipts veto sleep. Eligible input resumes the exact saved history. Explicit Stop cancels desired activation and stays stopped.

Unexpected failure closes the affected generation before bounded recovery. Transient retries back off from one to sixty seconds; authorization/configuration conflicts require action. Failed cleanup blocks a replacement writer. The controller reports incidents to the owner’s private crossfire management DM. Lost contact is unknown execution state; a dead controller cannot report itself.

After Node/C# fleetd is killed, a native Codex app-server can remain alive. Its history writer lock refuses a competing writer; those adapters do not enforce controller lifetime after SIGKILL. Rust’s packaged Linux process guard observes the exact parent pidfd and terminates its owned native group on exit. That mechanism does not contain arbitrary subprocesses that escape the group. A full host restart, where old processes are gone, is a different case. No implementation scans process names, adopts an orphan or copies its history to bypass ownership. These protections differ by implementation.

Native terminal access#

fleet agent contexts FLEET INSTANCE lists exact retained histories. fleet agent attach returns a running-session command, not another process, listener or forked history. The token itself is not printed. Closing the TUI leaves the managed engine running.

Pi RPC does not support live TUI attachment. Its API returns unsupported without starting a second writer. It has no emulated native permission sandbox; tools run with controller-user privileges.