# Fanful hosted agent runtime boundary

Fanful's current recommendation is external-first. Custom agent reasoning,
provider-specific SDK code, and open-ended automation should run in the
external agent, MCP client, or operator process. Fanful should host only narrow,
auditable worker families after their inputs, outputs, limits, confirmation
gates, and rollback behavior are explicit.

## Decision for now

- No general hosted worker runtime is enabled.
- No arbitrary third-party code runs inside Fanful infrastructure.
- MCP, HTTP manifests, action contracts, workflow triggers, agent sessions, sync
  jobs, and the SDK starter remain the primary integration path.
- A no-runtime path is valid: agents can stay external-first while Fanful
  provides contracts, redacted readbacks, and confirmation-gated write wrappers.

## What Fanful may host later

Fanful-managed workers are only candidates when they are deterministic,
bounded, and tied to an existing contract:

- Signed workflow-trigger handlers that read current state before acting.
- Cursor/checkpoint sync jobs for public or creator-approved data imports.
- Short-lived preview or reconciliation workers that produce redacted summaries.
- Delivery workers that call already-confirmed Fanful write wrappers with
  idempotency, stale-state checks, audit correlation, and cancellation.

## What stays external

- Open-ended reasoning, browsing, or code execution.
- Provider-specific app logic that is easier to audit in an external repo.
- Creator speech, public posting, moderation, email sending, going live,
  changing prices, checkout starts, payment state, or destructive actions unless
  the current action contract requires explicit human confirmation first.
- Raw secrets, bearer credentials, payment identifiers, private listener ids,
  private invite links, media URLs, media tokens, device ids, and raw database
  row ids in model-visible logs.

## Run record contract

Every hosted candidate needs a model-visible run record before implementation.
The record must include status, logs, correlation id, idempotency key, redacted
inputs and outputs, limits, approval state, cancellation semantics, and links to
the current action contract or manifest.

```json
{
  "version": "agent-hosted-runtime-run.v1",
  "id": "agent-run-preview-live-support-0001",
  "runtime": {
    "mode": "external-first",
    "hosting": "not-enabled",
    "executor": "external-agent",
    "relatedIssue": 1198
  },
  "status": "approval_required",
  "correlationId": "runtime-boundary-demo-2026-05-16",
  "idempotencyKey": "runtime-boundary-demo-approval-2026-05-16",
  "actor": {
    "kind": "creator_admin",
    "artistRef": "artist:laurel-public",
    "displayName": "Artist admin"
  },
  "client": {
    "id": "fanful-runtime-boundary-smoke",
    "kind": "codex",
    "transport": "mcp",
    "promptVisibleCredentials": false
  },
  "capability": "listener.support-checkout.preview",
  "scopes": [
    "public:read",
    "listener:checkout:preview"
  ],
  "startedAt": "2026-05-16T14:12:53.000Z",
  "completedAt": null,
  "limits": {
    "maxWallClockSeconds": 600,
    "maxRetries": 2,
    "retryBackoff": "exponential-with-jitter",
    "approvalExpiresSeconds": 900,
    "maxModelVisibleLogBytes": 8000,
    "cancellation": "required-before-requeue"
  },
  "inputs": {
    "redaction": "model-visible-summary",
    "manifest": "https://fanful.net/api/agent/listener-experience",
    "actionContract": "https://fanful.net/api/agent/action-contracts?audience=listener&domain=checkout",
    "summary": {
      "targetKind": "support",
      "targetRef": "support:live-room-donation",
      "amountCents": 2500,
      "currency": "usd",
      "liveEventRef": "live-event:laurel-studio-room"
    }
  },
  "logs": [
    {
      "sequence": 1,
      "at": "2026-05-16T14:12:54.000Z",
      "level": "info",
      "visibleToModel": true,
      "message": "Loaded public listener support preview manifest."
    },
    {
      "sequence": 2,
      "at": "2026-05-16T14:12:55.000Z",
      "level": "info",
      "visibleToModel": true,
      "message": "Validated confirmation copy against agent-write-envelope.v1 in dry-run mode."
    },
    {
      "sequence": 3,
      "at": "2026-05-16T14:12:56.000Z",
      "level": "approval",
      "visibleToModel": true,
      "message": "Human confirmation required before a checkout-start write can run."
    }
  ],
  "outputs": {
    "visibleToModel": {
      "preview": "Support donation checkout for $25.00.",
      "nextAction": "Ask for exact confirmation before calling listener.checkout.start.",
      "redactedFields": [
        "authorization header",
        "listener account identifiers",
        "Stripe identifiers",
        "checkout URLs",
        "raw database row ids"
      ]
    },
    "privateReferences": {
      "creatorPrincipalId": "redacted",
      "listenerPrincipalId": "redacted",
      "paymentProviderRef": "redacted",
      "bearerCredential": "redacted"
    }
  },
  "approval": {
    "required": true,
    "status": "pending",
    "destructive": false,
    "sensitiveDomains": [
      "checkout"
    ],
    "confirmationText": "I confirm listener.checkout.start for Support donation checkout for $25.00.",
    "nextStep": "Use agent-write-envelope.v1 with the current manifest state and this correlation id."
  },
  "audit": {
    "recordType": "agent-hosted-runtime.preview",
    "linkedSession": "agent-session-creator-live-0001",
    "linkedActionContract": "agent-write-envelope.v1",
    "rawPrivateInputsStored": "not-stored"
  }
}
```

## Required limits

- Maximum wall-clock runtime: 10 minutes until a concrete worker family proves
  it needs more.
- Maximum retries: 2 automatic retries with jittered exponential backoff.
- Approval TTL: 15 minutes for sensitive creator/listener actions.
- Cancellation: every queued or running job must have a cancellation/readback
  path before it can be retried.
- Logs: model-visible logs are redacted summaries capped at 8 KB per run.
- Secrets: credentials stay in headers, bindings, or MCP client config, never
  in prompts, public manifests, work-log entries, or model-visible logs.

## Relationship to current Fanful surfaces

- Workflow triggers notify agents about redacted events. They do not grant write
  permission.
- Agent sessions record redacted multi-step run history, pending approvals,
  completed tool calls, and cancellation. They do not execute code by
  themselves.
- Sync jobs define cursor, checkpoint, duplicate-safe resume, and drift-report
  records. They do not grant provider write permission.
- MCP tools and HTTP manifests expose the current capability boundary.
- Action contracts and agent-write-envelope.v1 are mandatory before any
  mutating worker calls a Fanful write wrapper.
- Audit records must link the run id, correlation id, idempotency key, actor,
  client, and confirmation text without exposing raw private identifiers.

## Follow-up policy

Open implementation issues only for concrete worker families, such as catalog
drift reconciliation, work-log feed mirroring, or confirmed live-room delivery.
Do not open a generic marketplace or arbitrary-code runtime until Fanful has a
real worker family that needs it.
