Source Hosts And Streams

Summary

AgentInbox should stop treating every provider feed or endpoint as a separate top-level source kind.

Instead, it should separate:

This keeps the provider/account runtime small and shared, while allowing many concrete feeds to exist under one host without exploding the top-level source model.

This RFC proposes:

Problem

Today the model trends toward making each provider feed a top-level source kind.

That works for a small number of builtin cases, but it scales poorly.

Examples:

And for X, the problem gets much worse:

If each of these becomes a separate top-level source kind, several problems follow:

Goals

Non-Goals

Core Design

1. Separate Host From Stream

The top-level hosted object should represent the provider/account/runtime context, not the concrete feed.

Suggested layers:

SourceHost

The shared provider/account/auth/runtime context.

Examples:

Responsibilities:

SourceStream

A concrete feed or append-only stream under a host.

Examples:

Responsibilities:

Subscription

An agent-specific filter and delivery rule over a concrete stream.

This stays conceptually the same as today.

2. Shared Host, Separate Checkpoints

One reason this split matters is checkpoint ownership.

These are not the same feed and should not share checkpoint state:

They may share:

But they must not share:

That makes stream the right unit for polling and checkpointing, not host.

3. Top-Level Source Kinds Should Collapse Toward Hosts

The public type surface should move toward a smaller set of provider-facing host kinds.

Examples:

Then each host exposes stream kinds.

Example GitHub stream kinds:

Example X stream kinds:

This keeps the public model much smaller without losing feed-level specificity.

4. Streams Are The Real Reusable Hosting Unit For Polling

The shared-source principle still holds, but the concrete unit of reuse becomes more precise:

That means multiple agents can share:

without needing:

5. Creation Order Should Be Explicit

The operational lifecycle should be:

  1. create source host
  2. create stream under that host
  3. create subscription on that stream

This reflects the actual ownership model:

This should be the default mental model in CLI, API, and docs.

Proposed Shapes

Host

Suggested shape:

{
  "sourceId": "src_github_default",
  "sourceType": "github",
  "config": {
    "auth": "github-default"
  }
}

Stream

Suggested shape:

{
  "streamId": "stm_repo_events_agentinbox",
  "sourceId": "src_github_default",
  "streamKind": "repo_events",
  "streamKey": "holon-run/agentinbox",
  "config": {
    "owner": "holon-run",
    "repo": "agentinbox"
  },
  "checkpoint": "..."
}

CI example:

{
  "streamId": "stm_ci_agentinbox",
  "sourceId": "src_github_default",
  "streamKind": "ci_runs",
  "streamKey": "holon-run/agentinbox",
  "config": {
    "owner": "holon-run",
    "repo": "agentinbox"
  },
  "checkpoint": "..."
}

X search example:

{
  "streamId": "stm_x_search_agentinbox",
  "sourceId": "src_x_default",
  "streamKind": "search",
  "streamKey": "query:agentinbox",
  "config": {
    "query": "agentinbox"
  },
  "checkpoint": "..."
}

5. Capability Discovery Should Be Split Too

The host and stream expose different capabilities.

Host-Level Schema

Host discovery should answer:

Stream-Level Schema

Stream discovery should answer:

Suggested CLI direction:

agentinbox source schema <sourceId>
agentinbox stream schema <sourceId> <streamKind>
agentinbox stream schema preview <sourceType> <streamKind> [--config-json JSON]

The key point is:

6. Mapping To UXC

The recommended split should remain:

uxc owns

AgentInbox owns

The intended correspondence is:

This keeps uxc focused on capability execution while AgentInbox owns the product event model.

7. Checkpoint Ownership Belongs To Streams

Checkpoint state should belong to streams, not hosts and not subscriptions.

Host should own

Stream should own

Subscription should own

This is essential because different feeds under one host must not share checkpoint state.

Examples:

8. Compatibility Mapping

Current builtin kinds should not break immediately.

Instead, treat them as compatibility aliases that resolve to:

Examples:

This gives a migration path:

Why This Fits The Product Boundary

This keeps the current AgentInbox boundary intact.

AgentInbox still owns:

What changes is just the precision of the internal and public model.

This model also preserves the core principle:

Migration Path

Phase 1

Introduce stream internally while preserving current public source kinds.

Map current builtins such as:

to an internal host-plus-stream representation.

Phase 2

Add stream registry and stream schema discovery.

Move checkpointing and feed-specific polling state fully onto streams.

Expose the host -> stream -> subscription creation order in CLI and API design.

Phase 3

Expose smaller host-level source kinds publicly for new providers.

New providers such as x should launch on the new model directly:

Open Questions

Recommendation

Adopt a three-layer model:

Use compatibility aliases for existing builtin source kinds, but stop treating every new provider feed as a new top-level source kind.

This gives AgentInbox a scalable model for providers such as GitHub and X without losing shared hosting, clean activation, or explicit delivery context.