---
name: outloop-access-fallback
description: "Resolve Outloop access, choose API then provider MCP then browser for an authorized operation, recover from technical or method failures, and respect explicit refusals. Read during bootstrap, scheduled intake and operator execution. Distinguish Local Bridge reachability, browser automation and tenant identity; do not use for creating a parallel runtime."
---

# Outloop access and recovery

**Component version:** public-2.5-rc.3. Canonical access owner for this pack.

## Outloop itself is reached through its Local Bridge

Resolve the active connected host workspace from actual authorized file access and its Outloop
managed instructions. Do not infer a host mount from a folder name, a chat statement, a cloud
sandbox, or the connector/plugin list. Resolve this workspace's `.claude/kestrel-direct/` and its
pending/result protocol. A bridge absence in the connector list means nothing.

Use the request/result contract actually supplied by the host. Write a unique request JSON to
`pending/<id>.json`, finish the write, and publish its empty `<id>.done` marker LAST. Read only the
matching `results/<id>.result.json` after `<id>.result.done` appears. Request fields are flat:
`tenant`, `service`, `verb` and the documented operation fields. Do not hide method/path/body
inside an invented `payload`, or add `task_run_id`, `browser_session` or credentials not required
by the live schema. URL-encode query parameters in `path` when that is the documented bridge
shape; never invent a separate ignored query field. Provider schemas still apply.

A bounded preflight uses `outloop.grants.check` for an actually configured service. An answered
refusal proves transport reachability, NOT authorization or provider connectivity. `PREFLIGHT_OK`
without an external call proves a grant check, NOT the provider workflow. Read `secret_exposed`
as a boolean; missing is UNKNOWN, never silently false. Do not redact away evidence booleans.

This section owns Local Bridge observation semantics. The bundled `scripts/bridge_probe.py` consumes
this contract after host access and identity verification. A `.result.claimed` marker proves request
acceptance, including queued/assigned/executing/provider-starting states. A completed result is read
only after `.result.done`; an explicit denial is terminal and is never reissued.

A bounded observation of an accepted request returns `BRIDGE_REQUEST_RUNNING` with request ID and
last observed state. Continue observing that SAME request; never re-drop it. An observation deadline
is not a task failure or a disconnected bridge. Even a claim marker that disappears does not erase
observed acceptance. Resume with `--request-id` and `--accepted` when the prior receipt proves it.
A short silent observation returns `BRIDGE_REQUEST_TIMEOUT`, with `last_observed_state: no_marker`;
it is inconclusive. For the full host silence contract, wait 20 seconds for done or claimed, then
wait 10 seconds and retry the safe preflight once only if still totally silent; watch both IDs.
Only total silence after that bound, a missing channel or an inaccessible channel warrants
`NOT_CONNECTED_TO_OUTLOOP` with `no_answer_after_retry`, `channel_missing` or `channel_not_writable`.
The helper’s exit code is 0 for a verified grant, 3 for pending/inconclusive observation, and 2
for denial/protocol/unavailable outcomes. If a previously accepted request cannot be observed because
its channel disappears, preserve acceptance and report observation unavailable, never a fresh
connection verdict for that request. The default 20-second window performs the bounded silence
protocol; shorter windows are
observation-only and cannot prove disconnection. These local status codes are not new server enums.
Do not fabricate responses, make a fake bridge or substitute another tenant path.
If actual host file tools are missing, report that capability gap and the precise mount action.

## Canonical per-operation order

1. **API first**, through Outloop where it brokers that operation. Use the documented viable API;
   do not repeatedly probe known-unsupported verbs. Outloop unavailable as a transport does not
   permit assuming its policy, resource boundary or license. Continue independent work only with
   existing verified authorization; restore the bridge before claiming Outloop verification.
2. **Provider MCP second** for the unsupported or technically failed portion, if actually available
   and permitted for that operation. No separate registration bureaucracy is required when the
   existing task/workspace policy already authorizes the route. Presence alone is not permission.
   Verify the requested immutable account/resource against the authorized boundary. A shared MCP
   may serve multiple tenants but every call must stay inside the current tenant's allowed target.
   Do not enumerate unrelated accounts for experimentation. If no safe target verification exists,
   the route is unavailable for sensitive work. Complete supported parts and use another route for
   the remainder, without duplicating writes or mixing inconsistent reporting snapshots.
3. **Browser next** for the remainder, selected as below. A Playwright MCP is a browser-control
   transport in this tier; it is not a provider data API just because MCP is in its name.
4. **Alternative method**: authorized source assets, deterministic editing/compositing, another
   existing skill or another practical implementation. Follow authority and failure-recovery.

A technical failure or missing capability may change route. An explicit resource, tenant, action,
approval, licensing, privacy or safety refusal stops the refused operation on ALL routes. An HTTP
status/code name alone cannot decide which kind occurred; inspect the actual decision and reason.
A partial permission denial is not an unsupported method. Never rotate credentials or widen grants
as a routine first response. No found keys, copied cookies, passwords, auth headers or agent .env.

## Live contract conflict

Read the current Outloop-managed contract, including any `CLAUDE.md` / `AGENTS.md` policy block.
Do not overwrite it. If it forbids MCP, skip MCP; proceed to a browser only if that operation and
route are separately allowed. `Outloop ONLY` is not permission to evade the same refusal in a UI.
Record the actual conflict and submit `source_of_truth_conflict` through the supported learning
mechanism; escalate a generator change as `PRODUCT_OR_RUNTIME_CHANGE_REQUIRED`. Continue other
allowed work. Do not label the blocked MCP tier production-proven. A permission change belongs
at the managed generator/owner, not a hand-edited tenant copy.

## Choose a browser by capabilities, not its name

First read any current Outloop-declared browser preference, then inspect actual reachable tools,
profile identity, permitted resource and action capabilities. Prefer that declared route if usable.
A managed-login profile is authentication infrastructure, not proof of a Playwright/browser route.
An empty list of local MCP servers does not exclude a remote or Outloop-brokered browser.

Otherwise select the most suitable available authorized route: Playwright-controlled Chrome,
another approved Playwright browser, Claude in Chrome, or the host's approved browser capability.
Use semantic anchors and read-back. Do not open an in-app pane merely because it is first in the
list. Never call an extension connected merely because its tools are listed: check reachability and
account/profile identity without exposing secrets.

For unattended runs prefer a route requiring no human click. Pre-granted site access is not the
same as available tools. If all suitable routes need user interaction, report a concrete readiness
gap promptly; do not hang. Computer Use is optional and must never be required or requested when
the owner has disallowed it. Do not auto-install extensions, servers or developer tools.

Routes may be combined when useful, with explicit handoff, same authorized target and identity
re-verification; do not silently switch user identities, copy login/session material, or repeat an
uncertain mutation. Outloop-managed login is used only via its supported hidden-secret interface.
No universal Playwright/Chrome default is asserted by this pack.

## Resource identity controls

This section owns generic resource verification. Verify the Outloop workspace first and then the
resource using its tenant-approved binding/control; do not mandate an immutable platform account
field that the approved workflow does not expose. The Bmby Browser Reader owns its Source Label
predicate: when approved for that tenant, it is a valid report identity/resource control. Permit
only the minimum approved view access needed to inspect that control; do not consume, export or
persist report data until it passes. A missing control stays unverified. A mismatching Source Label
stops with `BROWSER_RESOURCE_MISMATCH` (or the runtime's `RESOURCE_MISMATCH`); no fallback may bypass
that mismatch. Re-verify the same approved control after a login or route change. This exception
does not authorize mutations or replace the Outloop workspace binding.

## Evidence and outcomes

Record the operation, route selected, rejected alternatives and reason, verified target and result.
`RESOLVED_VIA_MCP` / `RESOLVED_VIA_BROWSER` describe successful routes, not approvals.
`RESOURCE_MISMATCH` stops the offending route; preserve legacy `BROWSER_RESOURCE_MISMATCH` as
an accepted platform-specific alias with the same safety behavior. Never rewrite provider codes.
`BROWSER_ROUTE_UNAVAILABLE` means the required browser capability is not usable now.
`NOT_CONNECTED_TO_OUTLOOP` means the workspace bridge cannot be reached; it is not an API denial.

Use the execution contract's real claim/report fields; local evidence classifications do not create
new server enums. Return useful completed work, exact remaining boundary and one next action.
