OSCAR Gateway plugin thumbnail

OSCAR Gateway

Connects authorized Agent Zero profiles as private OSCAR buddies, with a WebUI Buddy List, live profile and Mesh observability, persistent conversations, bounded recovery, and private Tailscale connectivity.

Author TerminallyLazy 1 stars Version 0.1.0 Updated

Screenshots

OSCAR Gateway screenshot 1

README

OSCAR Gateway

OSCAR Gateway is a custom Agent Zero plugin that exposes authorized Agent Zero profiles as stable AIM buddies, carries private one-to-one OSCAR messages into persistent Agent Zero contexts, and provides a durable, bounded agent mesh.

Release status: release candidate. AIM 5.9.6089 and Pidgin 2.12 are target/manual-gate clients, but neither client is compatibility-certified yet. The deterministic client and automated suite cannot substitute for the real client gates in the manual runbook.

The fail-closed defaults keep the listener, managed Tailscale integration, and profile autonomy off. Mesh services are available after plugin activation, but new mesh work remains subject to current grants, policy, and the durable A0Mesh pause flag.

Start here

OSCAR Gateway supports three related workflows. You can use the first one without configuring a legacy AIM client or opening a network listener.

Goal What to configure
Chat with Agent Zero profiles from the WebUI Enable the plugin, open an Agent Zero chat, then open Buddies in the right canvas. No OSCAR account or listener is required.
Connect Pidgin or AIM Create an OSCAR account, grant exact published profiles, choose a network mode, then enable the listener.
Delegate work through Agent Mesh Keep mesh.enabled on, grant only the required Mesh permissions to external accounts, and use the oscar_mesh tool or the A0Mesh control buddy.

The important names used throughout this guide are:

  • profile endpoint: one exact global profile or project/profile pair;
  • buddy: the stable OSCAR alias published for an endpoint;
  • OSCAR account: a login used by an external AIM-compatible client;
  • A0Mesh: the virtual control buddy for observing and controlling authorized Mesh work;
  • Buddy List: the plugin-owned Agent Zero canvas showing published profiles, live presence, and bounded Mesh metadata.

Recommended reading order:

  1. Install the plugin.
  2. Follow the quick start.
  3. Read Network modes and tunneling before allowing a client outside Agent Zero's container.
  4. Read Agent mesh before granting Mesh permissions or enabling autonomy.
  5. Use the troubleshooting table and manual runbook for release or compatibility work.

Scope and core boundary

Release 0.1.0 implements the OSCAR messaging vertical slice needed by the two target clients:

  • legacy MD5 challenge authentication and a combined auth/BOS listener;
  • service negotiation, SSI roster delivery, and buddy presence;
  • one-to-one ICBM channel 1 text, acknowledgements, durable inbound deduplication, reconnect delivery, Unicode handling, and bounded long-message chunks;
  • all enabled global Agent Zero profiles and enabled project-local profile variants from active projects;
  • a private persistent human context for each exact account/profile endpoint pair;
  • a durable agent mesh, the A0Mesh OSCAR control buddy, bounded recovery, and configurable per-endpoint autonomy;
  • loopback, explicit trusted-CIDR networking, and private raw-TCP Tailscale Serve.

It does not implement file transfer, chat rooms, public Internet exposure, Tailscale Funnel, public tunnel providers, or compatibility promises for newer OSCAR clients.

All runtime code, hooks, APIs, tools, prompts, WebUI assets, SQLite state, and Tailscale ownership records live under usr/plugins/oscar_aim. The plugin uses published Agent Zero extension, hook, API, tool, project, profile, and context interfaces; it does not patch agent.py, initialize.py, or another Agent Zero core file. The plugin also installs no Python package: backend verification uses the existing framework runtime at /opt/venv-a0.

Compatibility matrix

Client or harness Intended coverage Current status
Deterministic standard-library client Automated auth/BOS, service, SSI, presence, ICBM, malformed input, restart, dedupe, and tunnel fixtures Automated harness; not a real-client certification
Pidgin 2.12 Legacy MD5 with transport encryption disabled, direct trusted path, and private Tailscale Serve Target/manual gate; not compatibility-certified yet
AIM 5.9.6089 Corrected nested-MD5 login, combined-port redirect, direct trusted path, and private Tailscale Serve in an isolated legacy OS Target/manual gate; not compatibility-certified yet
Other OSCAR clients No declared coverage Unsupported until added to the matrix and gated

A release can be labeled compatibility release ready only after every mandatory deterministic, Pidgin, AIM, mesh, recovery, tunnel, update, and uninstall gate is recorded as passing. An unavailable real client, an unrun mandatory gate, or a failing assertion keeps the label at release candidate.

Install the plugin

Plugin Hub or Git installer

If OSCAR Gateway appears in your Agent Zero Plugin Hub:

  1. Open Plugins from the dashboard or sidebar.
  2. Open Browse or Install, search for OSCAR Gateway, and select it.
  3. Review the source link, README, requested behavior, and publisher.
  4. Choose Install, then enable oscar_aim in the installed plugin list.

If the entry is not yet present in your Plugin Hub index, use the same Install window's Git tab. Enter this repository URL and choose Clone & Install:

https://github.com/TerminallyLazy/oscar_aim.git

The installer validates the plugin and places it under usr/plugins/oscar_aim. A private-repository access token is not required for the public URL above. Always verify the publisher and URL through a trusted channel before installing third-party code.

Command-line install

The source tree must be the direct plugin directory, not one level below it. Run these commands in the Agent Zero environment, replacing /a0 if that is not the actual Agent Zero root:

cd /a0
test ! -e usr/plugins/oscar_aim
PLUGIN_REPOSITORY_URL='https://github.com/TerminallyLazy/oscar_aim.git'
git clone -- "$PLUGIN_REPOSITORY_URL" usr/plugins/oscar_aim
test "$(git -C usr/plugins/oscar_aim rev-parse --show-toplevel)" = "/a0/usr/plugins/oscar_aim"

Verify the publisher and repository URL through a trusted channel before installing. Pin and record the exact plugin commit used for a release gate. Do not force-add this custom plugin to the parent Agent Zero repository; usr/ is intentionally local runtime state.

Before activation, validate the package with Agent Zero's framework runtime:

cd /a0
/opt/venv-a0/bin/python -c "from plugins._plugin_installer.helpers.install import validate_plugin_dir; meta = validate_plugin_dir('/a0/usr/plugins/oscar_aim', 'oscar_aim'); print(meta.model_dump())"
/opt/venv-a0/bin/python -c "import usr.plugins.oscar_aim; import usr.plugins.oscar_aim.helpers.runtime; import usr.plugins.oscar_aim.hooks"
node --check usr/plugins/oscar_aim/webui/oscar-store.js
git -C usr/plugins/oscar_aim fsck --no-progress

Start Agent Zero with the framework runtime, read the actual WebUI URL from its startup output or Docker mapping, and enable oscar_aim in the plugin manager:

cd /a0
/opt/venv-a0/bin/python run_ui.py

Do not assume a WebUI port.

Updating

Prefer Agent Zero's plugin update action because it invokes the plugin's pre_update and post-update install hooks. The pre-update hook fences new work, stops the listener and exact durable tunnel, cleans only plugin-owned transient paths, and leaves the current database for the migration hook.

For a standalone Git update, first use Network > Stop, wait for exact cleanup, stop the Agent Zero process, verify the remote and branch through a trusted channel, and only then fast-forward the plugin checkout:

cd /a0
git -C usr/plugins/oscar_aim status --short
git -C usr/plugins/oscar_aim remote -v
PLUGIN_REMOTE='replace-with-verified-remote'
PLUGIN_BRANCH='replace-with-verified-branch'
git -C usr/plugins/oscar_aim pull --ff-only "$PLUGIN_REMOTE" "$PLUGIN_BRANCH"

If no verified remote exists, replace the stopped source tree from a verified artifact instead of inventing one. On restart, keep the listener disabled while the install hook validates the owned data boundary and runs migrations. Then repeat the framework-runtime checks and the update gates. The pre-v3 reset boundary below is an exception to normal in-place persistence.

Quick start

1. Enable the plugin safely

Enable oscar_aim from Agent Zero's installed plugin list. The shipped defaults do not open a network port: server.enabled and tailscale.managed are false, and endpoint autonomy is off. Activation initializes the plugin database and discovers enabled Agent Zero profiles.

Open the OSCAR Gateway dashboard and check:

  • Roster contains the global profiles you expect and any enabled project-local variants;
  • Network reports the listener stopped and no plugin-owned tunnel;
  • Recovery has no unresolved startup or storage case.

2. Use the Agent Zero Buddy List

Open any Agent Zero chat, then choose Buddies from the right-canvas toolbar. On a narrow screen, the same control opens a modal window.

  • Select a profile to open its exact Agent Zero chat.
  • Select it again to return to the same Buddy List-created chat during the current WebUI session.
  • Watch the presence badge for Available, Running, Paused, Recovering, Needs attention, Offline, or stale status.
  • Expand A0Mesh to see bounded route states and recovery counts.

This local WebUI workflow needs no OSCAR account, client password, listener, or tunnel.

3. Create an external client account (optional)

Only complete this step when connecting Pidgin, AIM, or another controlled OSCAR client.

  1. In Accounts, create a legacy-safe screen name with grant mode scoped.
  2. Copy the generated password into an approved password manager immediately. It is shown once; the plugin stores only verifier material.
  3. In Roster, review the stable aliases and endpoint IDs.
  4. Use Replace access set to save the account's complete intended endpoint grants and Mesh permissions atomically.

A scoped account implicitly sees published AgentZero; every other real profile needs an explicit endpoint grant. all_profiles intentionally grants every current and future published real endpoint. It does not reveal an unpublished endpoint and does not grant any A0Mesh permission.

Grant Mesh access separately and by need:

  • mesh_observe shows A0Mesh and authorized metadata;
  • mesh_control additionally allows confirmation, pause/resume, and cancel;
  • mesh_content reveals authorized task content for lineages that account already owns.

4. Choose the connection path

Keep server.enabled: false until account grants and network settings are reviewed. Choose one path:

Client location Mode Operator responsibility
Same network namespace as Agent Zero loopback Use the loopback listener directly. In Docker, the host and container do not share loopback.
Docker host or controlled LAN/VPN trusted_network Add only the narrow source CIDR the listener actually sees, publish the matching TCP port explicitly, and keep the host firewall closed to other networks.
Another device on a private tailnet tailscale_private Use private raw-TCP Tailscale Serve, either operator-managed or the plugin's exact managed rule. Never use Funnel.

Read Network modes and tunneling before changing the mode. Then save the global plugin configuration, enable the listener, and confirm Network reports the intended bound and advertised address. Do not publish this legacy protocol to the public Internet.

5. Configure and test the client

Use the account's screen name and one-time password, the gateway's advertised host, and the selected external TCP port. For the Pidgin 2.12 target, use its legacy AIM account type and disable transport encryption for this controlled compatibility path. Run AIM 5.9.6089 only in an isolated legacy environment. Exact client settings and evidence fields are in the manual compatibility runbook.

Verify the smallest path first:

  1. The client authenticates and shows only its authorized buddy roster.
  2. Sending a short message to one buddy creates or resumes that account's private endpoint context in Agent Zero.
  3. The Agent Zero response returns to the same client conversation.
  4. Reconnect once and confirm the message is not executed twice.
  5. If Mesh access was granted, send status to A0Mesh; do not begin with a control mutation.

Keep the release label at release candidate until the real Pidgin, AIM, Mesh, recovery, and tunnel gates in the runbook are recorded as passing.

Agent Zero Buddy canvas

The plugin registers a Buddies surface in Agent Zero's right canvas without modifying Agent Zero core files. It lists every published global and project profile endpoint, shows live available/running/paused/recovering/error/offline presence, counts bounded active routes, signals stale snapshots, and keeps recent A0Mesh task and recovery metadata alongside the main chat. The same plugin hooks observe ordinary WebUI profile runs and OSCAR-, Mesh-, recovery-, and autonomy-owned runs; overlapping contexts remain busy until the last exact run finishes. This activity surface reads profile identity and bounded route metadata only. It never displays prompt, response, objective, or result text.

Selecting a real buddy opens or returns to an Agent Zero chat for that exact agent profile and activates its exact project when the endpoint is project-scoped. The Agent Zero WebUI session is the authority for this local navigation; it does not mint or reuse an OSCAR account credential.

At mobile widths the same surface opens as a floating modal. External AIM, Pidgin, and OSCAR Buddy clients remain separate protocol sessions and continue to see only the roster authorized for their own OSCAR account.

Configuration model

default_config.yaml is the shipped baseline. Agent Zero stores sparse JSON configuration documents for global, profile, project, and exact project/profile scopes. Each document is bounded to 65,536 bytes of canonical JSON, rejects unknown fields, and is validated before it is accepted.

Effective endpoint policy is composed broad to narrow:

  1. shipped defaults;
  2. global plugin configuration;
  3. profile-only configuration;
  4. project-only configuration;
  5. exact project/profile configuration.

Objects merge by field. Lists replace the inherited list; they do not append to it. Every intermediate effective configuration is parsed, so a narrower valid value cannot hide an invalid broader document.

Only these fields are legal in a scoped document:

  • profiles.published, profiles.display_text, profiles.status_text, and profiles.show_task_titles;
  • mesh.default_repair_profile, mesh.diagnosis_attempts, mesh.repair_attempts, and mesh.retry_attempts;
  • every autonomy.* field.

Listener, Tailscale, audit, profile-refresh, project-publication, and global mesh admission ceilings are process-wide and therefore global-only.

Server fields

Field Default Operator contract
server.enabled false Opens the listener only while the plugin is also enabled and Network Stop is not latched. Turning it off stops the listener and exact owned tunnel.
server.mode loopback One of loopback, trusted_network, or tailscale_private.
server.bind_host 127.0.0.1 Local bind. Loopback mode requires a loopback host; Tailscale mode requires exactly 127.0.0.1. A wildcard trusted bind requires an explicit non-loopback advertised host.
server.port 5190 Listener port, 1-65535. This is also the actual managed Serve target port after binding.
server.advertise_host empty Host placed in the BOS redirect. Remote modes require a usable non-loopback host. In Tailscale mode, leave it empty or make it exactly match the canonical tailscale.advertise_host.
server.allowed_cidrs [] Required in trusted_network. Source IPs outside these normalized CIDRs are rejected before protocol admission. Catch-all /0 networks are forbidden.
server.max_frame_bytes 16384 Maximum FLAP payload, 1,024-65,535 bytes.
server.max_message_bytes 8000 Maximum decoded inbound message and outbound chunk budget, 256-32,000 bytes.
server.keepalive_seconds 60 Server keepalive interval, 15-600 seconds.
server.idle_timeout_seconds 180 Connection idle deadline, 30-3,600 seconds.
server.auth_timeout_seconds 20 Authentication deadline, 5-120 seconds.
server.max_sessions 32 Total concurrent listener sessions, 1-1,024.
server.max_sessions_per_ip 4 Concurrent sessions for one observed source IP, 1-64.

Profile fields

Field Default Operator contract
profiles.refresh_seconds 15 Validated global compatibility field, 5-3,600. The current runtime reconciles candidates on Agent Zero framework job-loop ticks; this value does not create an independent timer in 0.1.0.
profiles.publish_project_variants true Globally enables discovery of enabled project-local profiles in active projects. It does not clone every inherited global profile into each project.
profiles.published true Effective endpoint visibility and route admission. false hides and denies the endpoint while retaining its persisted identity.
profiles.display_text empty Optional roster display override; empty uses the discovered profile title. Maximum 128 characters and 512 UTF-8 bytes.
profiles.status_text empty Optional public status text, maximum 96 characters and 96 UTF-8 bytes.
profiles.show_task_titles false Opt-in exposure of current task titles in presence metadata. Keep off when titles may contain private data.

Mesh fields

Field Default Operator contract
mesh.enabled true Global admission switch for new mesh execution. It does not open the OSCAR listener.
mesh.max_hops 4 Immutable root-lineage hop ceiling, 1-16. Child creation also rejects repeated endpoints and cycles.
mesh.max_concurrency 4 Shared mesh/recovery context capacity, 1-64.
mesh.default_deadline_seconds 900 Root task deadline, 30-86,400 seconds; children inherit the root deadline.
mesh.default_repair_profile developer Effective profile key used for bounded diagnosis and repair proposals. It must remain a current executable endpoint inside the immutable authority snapshot.
mesh.diagnosis_attempts 1 Effective diagnosis budget, 1-4.
mesh.repair_attempts 2 Effective deterministic-repair budget, 0-8.
mesh.retry_attempts 2 Effective safe retry/reconciliation budget, 0-8.

Tailscale fields

Field Default Operator contract
tailscale.managed false When true in tailscale_private, the plugin may reconcile one exact private raw-TCP Serve rule and, if necessary, one identity-tracked userspace daemon.
tailscale.external_port 5190 Advertised tailnet and Serve port, 1-65,535.
tailscale.local_port 5190 Validated compatibility field. In 0.1.0 the managed target always uses the listener's actual bound_port; changing this field does not redirect Serve elsewhere. Externally managed mode also does not consume it.
tailscale.advertise_host empty Canonical private advertised host. Required when managed is false; optional in managed mode, where a safe tailnet DNS name or IP may be discovered. Do not put a public host here.

Audit fields

Field Default Operator contract
audit.include_content false Accepted global policy field. The current AuditService always sanitizes content and secrets; setting this to true does not enable raw content storage in 0.1.0.
audit.retention_days 30 Validated global policy field, 1-3,650. Automatic age-based pruning is not implemented in 0.1.0, so do not treat this value as a deletion guarantee.

The authenticated status API exposes only audit event metadata. It does not serialize verifier material, challenges, cookies, credentials, raw frames, prompts, unrestricted exceptions, or task content.

Autonomy fields

Autonomy policy is effective per real endpoint and inherits through the scope order above.

Field Default Operator contract
autonomy.mode off off, event_driven, scheduled, or hybrid. Any enabled mode requires a non-empty mission.
autonomy.mission empty Bounded system mission for that endpoint, up to 4,096 characters. It is not extra authority.
autonomy.allowed_events [] Up to 100 unique event codes matching lowercase safe-code syntax. The shipped producer emits task.completed and task.failed; another syntactically valid code does not create an external event integration.
autonomy.allowed_targets [] Up to 1,024 current stable OSCAR aliases. At each wake they resolve case-insensitively to executable real endpoints and become an immutable endpoint-ID grant snapshot.
autonomy.interval_minutes 60 Scheduled interval, 1-10,080 minutes, used when daily_at is empty.
autonomy.daily_at empty Optional exact HH:MM daily time. When set, it replaces interval scheduling for that endpoint.
autonomy.quiet_hours_start empty Exact HH:MM; must be set together with quiet_hours_end.
autonomy.quiet_hours_end empty Exact HH:MM; must be set together with quiet_hours_start. Equal start/end means the entire day is quiet.
autonomy.timezone UTC IANA timezone used for daily schedule, quiet hours, and daily budget.
autonomy.max_concurrent_tasks 1 Per-autonomy-principal active root ceiling, 1-16, still bounded by global mesh capacity.
autonomy.daily_task_budget 4 Per-endpoint daily admission budget, 1-1,000. Pending confirmation intents are also bounded by this value.
autonomy.cooldown_seconds 300 Minimum delay after a reservation, 0-86,400 seconds. Exact duplicate event hashes are also suppressed.
autonomy.require_confirmation true When true, every non-read_only autonomous task becomes a durable human confirmation request before task admission.

Scheduled and event wakes never bypass current endpoint publication, stable target resolution, pause state, hop/cycle policy, deadline, capacity, budget, cooldown, or confirmation. Autonomy and recovery work do not recursively emit new autonomy terminal wakes.

Profiles, aliases, grants, and private contexts

All effective profiles

Global discovery includes every enabled profile returned by Agent Zero's global profile registry, including default, plugin-provided, and user-provided profiles. With publish_project_variants: true, the plugin also scans active projects and adds only enabled project-local profile definitions. An inherited global profile is not duplicated merely because a project can use it.

The durable endpoint keys distinguish identity:

global:<encoded-profile-key>
project:<encoded-project-key>:<encoded-profile-key>
virtual:mesh-control

Therefore a global profile and a project-local profile with the same profile key are different endpoints, aliases, grants, policies, and private contexts. Project-qualified endpoints activate their exact project before the first chat is persisted.

For account visibility:

  • scoped sees the published AgentZero endpoint plus explicitly granted, published real endpoint IDs;
  • all_profiles sees every published real endpoint, including newly discovered ones;
  • A0Mesh is virtual and becomes visible only with mesh_observe;
  • published: false denies roster visibility and new route execution in every grant mode.

OSCAR aliases are persisted printable ASCII identities matching [A-Za-z][A-Za-z0-9]{0,15}. AgentZero and A0Mesh are reserved. Other aliases begin with a readable profile/project form; collisions or overlength names receive a deterministic digest suffix. Endpoint UUID and alias are stable across ordinary refreshes, restarts, and v3-compatible updates.

When a discovered endpoint disappears, the registry marks it offline and creates an alias tombstone. The tombstone prevents that alias from being silently reassigned. If the exact endpoint key returns, its prior UUID and alias return to service.

Relink is explicit and never guessed. In the Roster tab, an administrator may relink only an endpoint that is offline, missing, and owns its tombstone to one exact currently discovered endpoint key that is not already persisted. The transaction preserves the old endpoint UUID and alias, updates its scope/profile identity, and removes the matching tombstone. Review all existing grants and contexts after an intentional relink because they now follow that preserved identity.

Account/profile context privacy

The plugin persists exactly one context binding for each (account_id, endpoint_id) pair. Two accounts messaging the same profile get separate Agent Zero chats. A global endpoint and its project-qualified variant also get separate chats. The binding is reused for later messages so the human has continuity only inside that exact pair.

Route metadata alone is never authority. Before dispatch, tool use, completion, or fault handling, the bridge revalidates the live context object, current delivery generation, persisted binding, enabled account, current grant, published executable endpoint, and exact endpoint identity. If the context is removed or mismatched, the binding is invalidated and no unrelated context is adopted.

Only a final response logged after the currently correlated OSCAR dispatch can become that delivery's outbound reply. Background output, another context's response, and stale metadata are not exported to the human account.

Credentials and transport security

Account creation and rotation generate a cryptographically random, compatibility-safe 16-character password with Python's secrets module. The API returns it in exactly one successful response. The dashboard holds it in an ephemeral modal; copying or closing clears the browser store. Account lists and audit history never return it. There is no password-recovery operation.

Only the 32-hex MD5 password verifier is persisted. Rotation replaces that verifier immediately, so the old password no longer authenticates. If a credential is lost, rotate it; if access should stop, disable the account. Never reuse an OSCAR password for Agent Zero, Tailscale, email, or any other system, and never paste it into logs, screenshots, captures, issues, or manual results.

OSCAR is plaintext legacy transport. The MD5 challenge flow avoids sending the password itself, but it does not encrypt roster data or messages and it is not a modern password-authenticated protocol. Anyone who can observe the raw path can read message content. A captured challenge/digest or a copy of the persisted verifier permits offline password guessing. Treat data/oscar.sqlite3 and its backups as credential-bearing private data. Use the generated high-entropy password, never a human-chosen or reused one.

Loopback reduces the path to the local network namespace. Trusted-network mode relies on the operator's LAN/VPN, firewall, and Docker boundary. Private Tailscale Serve encrypts the tailnet segment, but OSCAR remains plaintext at the client and local listener endpoints.

Unknown, disabled, malformed, and wrong-password logins use generic failures and rate-limited admission; they are not an account-enumeration interface.

Agent mesh

The mesh is a durable delegation broker, not a prompt convention. A profile can use the native oscar_mesh tool to send a bounded task to another authorized profile, inspect or cancel owned work, and return a correlated result. The model supplies only task intent fields; source identity, principal, grants, permissions, lineage, reply route, and claim ownership are derived from an exact live plugin context.

flowchart LR
    H["Authenticated OSCAR account"] --> S["Source profile context"]
    S --> B["Durable mesh broker"]
    B --> T["Authorized target profile"]
    T --> C["Optional bounded child"]
    T --> R["Correlated reply route"]
    C --> R
    B --> M["A0Mesh metadata and control"]
    B --> F["Recovery supervisor"]
    A["Per-endpoint autonomy principal"] --> B

Principals and immutable lineage

The broker recognizes three persisted principal kinds:

  • human: the authenticated OSCAR account UUID, with the account's exact endpoint-grant and mesh-permission snapshot;
  • autonomy: the source endpoint UUID, with targets resolved from that endpoint's configured stable aliases at wake time;
  • gateway-recovery: the internal bounded recovery executor, which carries no human mesh permissions and cannot become general user authority.

A child delegation does not create a broader principal. It preserves the root's principal, immutable endpoint-ID grant snapshot, permissions, lineage ID, deadline, recovery policy, and reply visibility. It adds a parent task ID, increments the hop count, and extends the visited endpoint path. Repeated endpoints, source-equals-target, unauthorized targets, expired deadlines, and hop-budget exhaustion fail before a child context is created.

Each envelope also freezes objective, success contract, effect class, idempotency key, source and target IDs, evidence references, and response route. Effect classes are read_only, idempotent, reconcilable, and unknown. They determine whether retry is safe and whether autonomous work requires human confirmation.

Task states are:

queued -> accepted -> running -> completed
                         |-> fault_detected -> diagnosing -> repairing
                         |                    -> retrying -> reconciling
                         |                    -> needs_attention / failed
                         |-> cancelled

Transitions and claims are persisted transactionally. Stable idempotency keys deduplicate repeated send_task intent. On restart, the broker reconciles owned attempts, reply injections, recovery work, and autonomy leases before it admits new work.

Native oscar_mesh operations

Profiles receive four tool operations:

  • send_task with target, objective, success_contract, effect_class, and a stable idempotency_key;
  • inspect with a task ID;
  • cancel with a task ID;
  • reply with the current task result.

The target is a current OSCAR alias. No operation accepts a caller-supplied principal, source, grant list, lineage, or reply context.

A0Mesh control buddy

An OSCAR account with mesh_observe sees the reserved A0Mesh buddy and can send these exact commands:

status
tasks [1-20]
why <task-id>
confirmations [1-20]
approve <request-id>
deny <request-id>
pause [generation]
resume [generation]
cancel <task-id>

mesh_observe permits status, principal-scoped task metadata, and why. mesh_control is additionally required for confirmation decisions, pause/resume, and cancellation. mesh_content permits authorized objective, contract, result, diagnosis, and repair-plan text where the principal already owns the lineage; without it, inspection is metadata-only. The optional pause generation is an optimistic concurrency fence. Control responses are stored transactionally and replayed exactly once for an exact inbound control route.

The durable A0Mesh pause blocks new mesh and autonomy admission. It does not disable the OSCAR listener or interrupt ordinary human/profile chat.

Recovery

When a task, listener, tunnel, delivery, agent execution, tool call, or autonomy lease faults, the supervisor creates or updates a recovery case with a stable case ID, redacted failure class, bounded evidence, generation, state, attempt budgets, and resumable conditions. It preserves the original failure even if a later diagnosis step fails.

For task recovery, the effective default_repair_profile may produce a bounded diagnosis and repair proposal. Recovery profile contexts are proposal-only: they do not receive normal tools or subagent delegation. A registered plugin-owned deterministic repair callback performs the actual mutation and a separate verifier must return explicit proof. Only then may the supervisor retry or reconcile an effect class the policy considers safe. Unavailable authority, an unverifiable repair, an unsafe effect, an external condition, or an exhausted budget becomes a concrete needs_attention case rather than a silent broad retry.

Configurable autonomy

Autonomy is disabled by default and configured at the same global/profile/ project/exact scopes as other endpoint policy. Each enabled endpoint has its own principal, mission, schedule or event allowlist, target-alias allowlist, quiet hours, timezone, concurrency ceiling, daily budget, cooldown, and confirmation rule. A wake snapshots executable target IDs and enforcement policy before an Agent Zero context runs. Later alias drift, unpublication, pause, or policy change cannot silently expand that snapshot.

For the safest rollout, enable one endpoint at a time, keep require_confirmation: true, grant only read_only work until the manual autonomy gates pass, and verify pause still allows ordinary human chat.

Network modes and tunneling

Loopback

loopback accepts only a loopback bind and loopback peers in the listener's network namespace. In Docker, container loopback is not host loopback. This mode is appropriate for in-container testing or a client deliberately placed in the same namespace; it does not create a host port mapping.

Trusted CIDR

trusted_network requires at least one narrow server.allowed_cidrs entry and rejects /0. The listener checks the source IP reported to its socket before protocol admission. In Docker that may be a bridge/NAT address rather than the client's original address, so inspect the controlled connection path and allow only the exact network the container actually observes.

The plugin does not edit Compose, publish a container port, change a firewall, restart Docker, create a VPN, or manage a reverse proxy. The operator must add and review an explicit host-to-container TCP mapping when needed, for example a 5190-to-5190 mapping matching the configured listener, and must keep the host firewall/VPN boundary narrow. Do not publish trusted-network mode to the public Internet.

Private Tailscale Serve

tailscale_private always binds the OSCAR listener to exactly 127.0.0.1. There are two ownership modes:

  • With tailscale.managed: false, tailscale.advertise_host is required. The plugin assumes an operator-managed private raw-TCP Serve path, labels the daemon and rule external, and never removes them. If Tailscale runs only on the Docker host, the operator must provide a reachable container target and manage the host-side rule; the container plugin cannot safely own it.
  • With tailscale.managed: true, the plugin feature-detects private raw-TCP Serve, reads both CLI status and LocalAPI state, waits for a healthy loopback listener, and reconciles one exact external-port-to-actual-bound-port rule. It can borrow a system or Agent Zero daemon without stopping it, or track one plugin-started userspace daemon by exact process identity and owned paths.

Managed mode refuses a conflicting rule and treats an identical pre-existing rule as borrowed. On disable, update, or uninstall it removes only a rule whose exact port, target, daemon identity, and durable fingerprint still match, and stops only an identity-matching plugin-owned daemon. It preserves unrelated Serve configuration and borrowed daemons.

The plugin never runs tailscale serve reset, never changes tailnet ACLs, and never creates Tailscale Funnel. It has no Cloudflare Tunnel, Microsoft Dev Tunnel, Serveo, public reverse-proxy, or other public-provider adapter. Remote support is private tailnet raw TCP only. See the official Tailscale Serve CLI reference.

Disable, export, uninstall, and cleanup

These controls have different scope:

Control Effect
A0Mesh pause Blocks new mesh and autonomy admission; human OSCAR chat continues.
Network Stop Sets a temporary administrative latch and stops the listener and exact owned tunnel. Network Reconcile clears the latch and applies current intent.
server.enabled: false Stops network exposure and exact owned tunnel while plugin storage, roster, dashboard, and mesh services remain available.
Plugin toggle off The runtime self-monitor stops listener/tunnel exposure even if no later extension tick arrives.
Plugin update Runs the lifecycle fence and exact cleanup, preserves a compatible database, then migrates and resumes under the new code.
Plugin uninstall Runs the same exact stop/cleanup hook before Agent Zero removes the plugin directory and its local data.

Config saves are schema-validated before persistence. Global saves request an orderly process reconcile; scoped saves refresh endpoint presentation, recovery, and autonomy policy. Network resources restart only when their effective process signature changes.

Metadata export

Version 0.1.0 has no one-click file export. Before an update or uninstall, an authenticated administrator may preserve an operator-owned copy of the dashboard's redacted status, account list, roster list, mesh/recovery metadata, network ownership status, and audit metadata. These are the same bounded POST surfaces used by the WebUI under /plugins/oscar_aim/{status,accounts,roster,mesh,network}. Use Agent Zero's authenticated/CSRF-protected UI or approved API tooling; do not weaken those protections for an export.

The redacted surfaces omit one-time passwords, verifiers, challenges, cookies, tokens, raw frames, prompts, unrestricted exceptions, and dashboard task content. A raw SQLite copy is not a metadata export: it contains credential-bearing and potentially private durable state and must be encrypted, access-controlled, and handled as a secret. Manual release results should contain only the non-secret fields allowed by the runbook.

Uninstall procedure

  1. In Network, choose Stop and wait for listener=stopped, tunnel=off, rule_owner=none, daemon_owned=false, and cleanup_verified=true.
  2. Resolve any exact listener/tunnel recovery case before deleting files. Never use a global Serve reset as a shortcut.
  3. Export only the redacted metadata needed for the operator record.
  4. Use Agent Zero's plugin uninstall action so hooks.uninstall fences work, stops the runtime, cleans the exact owned Serve rule/daemon, and removes transient paths before directory deletion.
  5. Verify no plugin-owned listener, Serve rule, daemon, PID, socket, symlink, service, or external file remains. Verify borrowed daemons/rules and unrelated Serve entries are unchanged.
  6. Verify usr/plugins/oscar_aim and its data/oscar.sqlite3 are absent only after the plugin manager completes. Do not delete another plugin or Agent Zero core state.

During pre-update cleanup, the database remains while data/runtime and the plugin-owned data/tailscale/runtime, tailscaled.sock, tailscaled.pid, and tailscaled.log transients are removed. During uninstall, Agent Zero's plugin deletion removes the complete plugin directory after the hook succeeds.

Pre-v3 database reset boundary

Pre-v3 local databases are reset-only and incompatible with exactly-once continuity because request identity was never persisted.

Here, “v3” means the inbound delivery deduplication identity domain, not the number of an unrelated SQLite migration. Pre-release v1/v2 identities included the session generation. V3 deliberately excludes it so an exact transport retransmit after fresh BOS authentication remains the same request. Legacy rows store only the resulting hash and ICBM cookie; they do not store the normalized request identity or original session generation needed to recompute a lossless v3 key.

Consequently, an in-place pre-v3 database can treat the first v3 replay as new work and execute it twice. No migration can honestly promise exactly-once continuity for those rows.

For a pre-v3 local development database:

  1. Use Network Stop, verify exact tunnel cleanup, disable the plugin, and stop the Agent Zero process.
  2. If a forensic backup is required, encrypt it and treat it as a credential; never restore it as a continuity-capable v3 database.
  3. Remove only data/oscar.sqlite3, data/oscar.sqlite3-wal, and data/oscar.sqlite3-shm after the process and plugin-owned network resources are stopped.
  4. Start Agent Zero, let the install hook create a fresh database, recreate accounts and exact grants, and keep the listener off until review completes.
  5. Rerun every restart, reconnect, and deduplication gate.

If reset is not acceptable, mark those gates blocked and keep the artifact at release candidate. Do not rewrite legacy hashes, bridge them heuristically, or claim continuity.

Troubleshooting by recovery-case ID

Use the recovery-case ID as the durable handle. Do not troubleshoot by pasting raw exceptions, chat content, credentials, or packets.

  1. Copy the case ID from the Recovery tab or the matching task's Why view.
  2. Record only case ID, task ID when present, component, operation, redacted failure class, state, generation, attempt counts, resumable-condition count, and recent reason codes.
  3. Fix the narrow external or plugin-owned condition without editing SQLite.
  4. For a task in needs_attention, use the dashboard's exact task Retry action after the condition changes. For listener or tunnel cases, use Network Reconcile. The supervisor rechecks generation, ownership, authority, budgets, and proof before proceeding.
  5. If a mandatory gate still fails, follow the runbook's diagnose-fix-regress-retest loop and keep the same case/correlation handle in sanitized evidence.
Symptom Check first Safe next action
Listener remains stopped or reports attention Effective server.*, Network Stop latch, bind/advertise rules, observed source CIDR, recovery component/operation Correct configuration or environment, then Network Reconcile; do not broaden CIDRs to /0.
Managed Serve reports attention Case ID, external port, daemon/rule owner, socket source, conflicting exact rule Restore the recorded daemon/rule identity or remove the external conflict, then Reconcile. Never run tailscale serve reset.
Login fails generically Account enabled state, newly rotated one-time password, client legacy-MD5/no-encryption settings, source admission Rotate once if the secret is uncertain; do not weaken generic auth responses or capture a live credential.
Buddy is offline/missing Roster endpoint key, missing timestamp, tombstone, Agent Zero profile enablement/project activation Restore the exact profile key, or perform one reviewed explicit relink to an exact discovered key.
Scoped account cannot see a profile Effective published, exact endpoint grant, grant mode, project-qualified identity Replace the complete access set with the intended endpoint ID; do not switch to all_profiles merely to hide a grant mistake.
Mesh delegation is denied mesh.enabled, durable pause/generation, current alias, immutable grant snapshot, hop/path/deadline/capacity Correct the source authority or choose an authorized target; never inject principal/grant fields.
Recovery reaches needs_attention Case ID, failure class, effective repair profile, attempt budgets, resumable condition, effect class Restore the exact condition and use task Retry; an unsafe or unverified repair remains attention.
Autonomous endpoint does not wake Effective mode/mission, supported event code, daily_at versus interval, timezone/quiet hours, budget/cooldown, target aliases, pause Change the narrow endpoint policy, then wait for the next framework tick; do not create an external event assumption.
Reconnect appears to duplicate work Database generation, exact request identity/cookie, delivery case/reason codes Stop testing immediately if the DB is pre-v3; reset it and rerun the deterministic regression before any real-client gate.
Update or uninstall cannot cleanly finish Listener/tunnel recovery case, ownership ledger, borrowed versus owned resources Resolve and verify exact cleanup before source deletion. Preserve borrowed resources and unrelated Serve rules.

Automated and manual release gates

Run package validation from the Agent Zero root with the framework runtime:

cd /a0
/opt/venv-a0/bin/python -c "from plugins._plugin_installer.helpers.install import validate_plugin_dir; meta = validate_plugin_dir('/a0/usr/plugins/oscar_aim', 'oscar_aim'); print(meta.model_dump())"
node --check usr/plugins/oscar_aim/webui/oscar-store.js
/opt/venv-a0/bin/python -c "import usr.plugins.oscar_aim; import usr.plugins.oscar_aim.helpers.runtime; import usr.plugins.oscar_aim.hooks"
git -C usr/plugins/oscar_aim fsck --no-progress

The stock production-ready image need not include pytest. Run the complete suite in an Agent Zero contributor/development runtime prepared from requirements.dev.txt, or inject the same reviewed read-only test site used by release evidence. Do not install test dependencies into a production runtime merely to execute this gate.

cd /a0
PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 \
  /opt/venv-a0/bin/python -m pytest \
  -p pytest_asyncio.plugin usr/plugins/oscar_aim/tests -q

Then complete the manual compatibility runbook, which records:

  • exact Agent Zero/plugin commits, framework Python, Docker mapping, client builds/OS, Tailscale version/owner, mode, UTC time, and operator initials;
  • deterministic auth, roster, presence, ICBM, malformed/partial, reconnect, dedupe, and tunnel-cleanup gates;
  • Pidgin 2.12 direct trusted and private Tailscale paths;
  • AIM 5.9.6089 direct trusted and private Tailscale paths;
  • mesh lineage, hidden-target rejection, injected failure, recovery proof, and dashboard/A0Mesh agreement;
  • per-endpoint autonomy schedule/event, quiet-hours, budget, cooldown, confirmation, pause, and no-recursive-wake gates;
  • compatible update persistence and exact disable/uninstall ownership cleanup.

Every failed mandatory gate requires a controlled reproduction, sanitized fixture when protocol-related, deterministic regression, smallest in-scope fix, focused automated retest, both affected network paths, and the complete release-candidate suite. There are no documentation waivers. A deterministic client pass alone never certifies Pidgin or AIM.

Contributor guide

  • Keep implementation changes inside this plugin. A new runtime dependency or Agent Zero core change requires a separate reviewed design; 0.1.0 uses the standard library and packages already in /opt/venv-a0.
  • Keep socket parsing and Tailscale work off Agent Zero's framework thread. All AgentContext creation, project activation, persistence, and communication go through the framework job-loop bridge.
  • Treat grants, endpoint identity, delivery generation, mesh lineage, autonomy leases, recovery generation, and tunnel ownership as enforcement data, not model instructions.
  • Preserve exact lifecycle ownership. Never stop a borrowed daemon, delete an unrelated Serve rule, use a global Serve reset, or leave a listener running after disable/update/uninstall.
  • Ground OSCAR state-machine changes in primary client source or a controlled, sanitized real-client fixture. Illustrative protocol samples do not override Pidgin's actual sequence.
  • Never commit raw PCAPs, TCP payloads, credentials, verifiers, challenges, digests, BOS cookies, tailnet identity material, private addresses, project names, chat content, or unrestricted exceptions. Use tests/tools/redact_capture.py only for controlled traffic and manually inspect its allowlisted output.
  • Add focused tests beside every behavior change, then run the complete plugin suite and the applicable manual client paths.

License and compatibility sources

OSCAR Gateway is distributed under the MIT License.

Primary and corroborating references:

The source references guide implementation; only recorded tests against the exact Pidgin 2.12 and AIM 5.9.6089 builds can change their compatibility status.