Delivery Handles And Source-Specific Operations

Summary

AgentInbox should keep outbound delivery as a first-class concern, but it should not force every provider into one generic deliver send interaction model.

The current deliver send shape works for sources that have a natural canonical text send/reply path, but it breaks down for providers such as GitHub, where “reply” is actually a family of distinct operations with different semantics and APIs.

This RFC proposes:

Problem

Today AgentInbox has a single outbound entrypoint:

The request can either:

This works acceptably for sources such as Feishu chat/message reply where the main operator intent is genuinely:

But it fits GitHub poorly.

For GitHub, a runtime may need to choose among several actions:

These are not one generic “reply”.

Trying to normalize them into a single send action creates several problems:

Current State

Current outbound delivery consists of:

Today the real provider-side implementations are intentionally narrow:

This is useful as a first proof that outbound routing belongs in AgentInbox, but it is not yet the right long-term operator model for multi-action sources.

Goals

Non-Goals

Design Principles

1. Standardize Routing, Not Meaning

The thing AgentInbox should standardize is:

The thing AgentInbox should not try to standardize too early is:

This is the same boundary we already apply inbound:

2. Delivery Handles Stay, But They Are Not The Whole Model

DeliveryHandle should remain the stable routing object captured on inbox items and events.

It should continue to answer:

But a handle alone is not enough to describe all possible outbound actions for that provider context.

For multi-action providers, the runtime needs:

3. deliver Is The Stable Execution Surface

AgentInbox deliver should be thought of as:

AgentInbox should not require a provider-native tool to be installed in order to complete outbound work.

Proposed Model

1. Keep DeliveryHandle As The Provider Context Object

Suggested continuation of the current shape:

{
  "provider": "github",
  "surface": "review_comment",
  "targetRef": "holon-run/agentinbox#110",
  "threadRef": "review_comment:123456789",
  "replyMode": "thread_reply"
}

This remains the source-owned opaque-enough execution context.

The important rule is:

2. Introduce Source-Specific Delivery Operations

Instead of assuming one generic send, a provider may expose operation descriptors.

Suggested shape:

{
  "handle": {
    "provider": "github",
    "surface": "pull_request",
    "targetRef": "holon-run/agentinbox#110"
  },
  "operations": [
    {
      "name": "add_comment",
      "title": "Add PR Comment",
      "inputSchema": {
        "type": "object",
        "required": ["body"],
        "properties": {
          "body": { "type": "string" }
        }
      }
    },
    {
      "name": "reply_in_review_thread",
      "title": "Reply In Review Thread",
      "inputSchema": {
        "type": "object",
        "required": ["body"],
        "properties": {
          "body": { "type": "string" }
        }
      }
    },
    {
      "name": "submit_review",
      "title": "Submit Review",
      "inputSchema": {
        "type": "object",
        "required": ["event"],
        "properties": {
          "event": { "type": "string", "enum": ["COMMENT", "APPROVE", "REQUEST_CHANGES"] },
          "body": { "type": "string" }
        }
      }
    }
  ]
}

These operations are source-specific.

Core does not need to know what submit_review means beyond:

3. Keep deliver send Only For Canonical Text Surfaces

Some sources really do have a natural canonical text action:

For those sources, deliver send remains useful.

Suggested rule:

Examples where deliver send remains a good fit:

Examples where it should not be the primary operator model:

4. Add Operation Discovery And Invocation

Suggested CLI direction:

agentinbox deliver actions --item <itemId>
agentinbox deliver actions --handle-json '{...}'
agentinbox deliver invoke --handle-json '{...}' --operation add_comment --input-json '{"body":"..."}'

Suggested HTTP direction:

This keeps one generic execution frame while letting providers keep their own action vocabulary.

5. Source-Specific Tool Choice Stays Outside Core

An agent may still choose to use:

That choice belongs to the agent/operator layer, not to the AgentInbox core contract.

The only thing the RFC requires is:

Operator Experience

The intended operator split becomes:

Any Runtime Or Operator

Use AgentInbox for:

Why This Fits The Product Boundary

This direction keeps the AgentInbox boundary clean:

It also avoids connector gravity:

Migration Path

Phase 1

Keep current deliver send intact.

Document it as:

Phase 2

Add operation discovery and invocation framing:

Implement it first for one provider where the difference is valuable, likely GitHub.

Phase 3

Teach inbox items and docs to expose better operation guidance while keeping AgentInbox operation descriptors available for automation.

Open Questions

Recommendation

Adopt the following product rule:

This gives AgentInbox a stable delivery model without forcing a fake universal reply abstraction across providers.