java.lang.Object
io.agentscope.harness.agent.gateway.channel.chatui.ChatUiChannel
All Implemented Interfaces:
Channel

public final class ChatUiChannel extends Object implements Channel
Default Channel implementation for direct Chat UI interactions: no external transport, no webhook, no websocket — the caller submits a ChatUiRequest programmatically and receives the agent reply reactively.

Suitable for:

  • Embedded web chat UIs that send HTTP requests to the harness
  • CLI tools and integration tests that need a typed API to the agent
  • Single-agent single-session scenarios where the default DmScope.MAIN collapses all conversations into one session

Obtaining an instance

The recommended way is through GatewayBootstrap.chatUiChannel():

 GatewayBootstrap gw = GatewayBootstrap.builder().model(model)
     .agent("main", b -> b.name("assistant").sysPrompt("..."))
     .build();
 ChatUiChannel chat = gw.chatUiChannel();
 chat.send("Hello!").block();
 
  • Field Details

  • Method Details

    • create

      public static ChatUiChannel create()
      Creates a Chat UI channel with the default DmScope.MAIN config.
    • create

      public static ChatUiChannel create(ChannelConfig config)
      Creates a Chat UI channel with an explicit config.
    • perPeer

      public static ChatUiChannel perPeer()
      Creates a per-peer Chat UI channel. Each distinct peerId gets its own session.
    • create

      public static ChatUiChannel create(Gateway gateway)
      Creates a Chat UI channel with a pre-wired gateway.
    • create

      public static ChatUiChannel create(Gateway gateway, ChannelConfig config)
      Creates a Chat UI channel with a pre-wired gateway and explicit config.
    • init

      public void init(Gateway gateway)
      Description copied from interface: Channel
      Called by the gateway bootstrap before Channel.start() to supply the auto-wired Gateway. Implementations that need a gateway but do not receive it at construction time should override this method. The default is a no-op.
      Specified by:
      init in interface Channel
    • start

      public void start()
      Description copied from interface: Channel
      Connects to the external event source and starts dispatching inbound messages. Programmatic channels may make this a no-op.
      Specified by:
      start in interface Channel
    • stop

      public void stop()
      Description copied from interface: Channel
      Disconnects from the external event source and releases resources. Programmatic channels may make this a no-op.
      Specified by:
      stop in interface Channel
    • channelId

      public String channelId()
      Description copied from interface: Channel
      Logical identifier for this channel (e.g. "chatui", "slack", "discord"). Must match ChannelConfig.channelId().
      Specified by:
      channelId in interface Channel
    • config

      public ChannelConfig config()
      Description copied from interface: Channel
      Returns the routing configuration for this channel.
      Specified by:
      config in interface Channel
    • applyRoutingConfig

      public boolean applyRoutingConfig(ChannelConfig newConfig)
      Description copied from interface: Channel
      Applies a new routing ChannelConfig (bindings, dmScope, defaultAgentId) without tearing down the channel's transport. Implementations that hold their Channel.config() in a mutable / volatile reference can override this to support hot reload of bindings.

      The default implementation returns false to signal that this channel does not support live config swap. Returning true means the swap was applied and subsequent inbound messages will route under the new config.

      Specified by:
      applyRoutingConfig in interface Channel
      Parameters:
      newConfig - the new routing configuration to install (channelId must match Channel.channelId())
      Returns:
      true if the config was applied live; false if the channel requires a restart to pick up the new config
    • dispatch

      public reactor.core.publisher.Mono<io.agentscope.core.message.Msg> dispatch(InboundMessage message)
      Description copied from interface: Channel
      Specified by:
      dispatch in interface Channel
    • previewRoute

      public RouteResult previewRoute(InboundMessage message)
      Returns the RouteResult this channel would produce for message without dispatching it. Useful for pre-computing the session key before sending.
    • deliver

      public void deliver(OutboundAddress address, List<io.agentscope.core.message.Msg> messages)
      Description copied from interface: Channel
      Delivers proactive outbound messages (e.g. subagent completion announces) to this channel's transport. Called by the gateway when an agent produces a reply that needs to be pushed to the originating channel/peer rather than returned synchronously.

      The default implementation is a no-op, suitable for pull-based channels that do not support proactive push.

      Specified by:
      deliver in interface Channel
      Parameters:
      address - the delivery target (peer, thread, account context)
      messages - the messages to deliver
    • pollOutbound

      public List<OutboundEnvelope> pollOutbound()
      Drains and returns all buffered proactive outbound messages. Returns an empty list if no messages are pending.
    • outboundQueueSize

      public int outboundQueueSize()
      Returns the number of buffered proactive outbound messages.
    • send

      public reactor.core.publisher.Mono<io.agentscope.core.message.Msg> send(String text)
      Sends a plain-text message in single-session mode (no peer id).
    • send

      public reactor.core.publisher.Mono<io.agentscope.core.message.Msg> send(String peerId, String text)
      Sends a plain-text message from a specific peer.
    • send

      public reactor.core.publisher.Mono<io.agentscope.core.message.Msg> send(SendOptions options, String text)
      Sends a plain-text message with explicit routing identity. The SendOptions determines the user identity and session key directly — no DmScope configuration required.
      See Also:
    • sendToSubagent

      public reactor.core.publisher.Mono<io.agentscope.core.message.Msg> sendToSubagent(String subagentId, String text)
      Sends a message directly to an exposed subagent, bypassing normal routing.
    • send

      public reactor.core.publisher.Mono<io.agentscope.core.message.Msg> send(ChatUiRequest request)
      Sends a structured ChatUiRequest and returns the agent reply reactively.
    • dispatchStream

      public reactor.core.publisher.Flux<io.agentscope.core.event.AgentEvent> dispatchStream(InboundMessage message)
      Description copied from interface: Channel
      Streaming variant of Channel.dispatch(InboundMessage). Returns fine-grained AgentEvents instead of a single reply.

      The default delegates to Gateway.runStream(io.agentscope.harness.agent.gateway.MsgContext, java.util.List<io.agentscope.core.message.Msg>) with the resolved route.

      Specified by:
      dispatchStream in interface Channel
    • sendStream

      public reactor.core.publisher.Flux<io.agentscope.core.event.AgentEvent> sendStream(String text)
      Streaming variant of send(String). Returns fine-grained AgentEvents.
    • sendStream

      public reactor.core.publisher.Flux<io.agentscope.core.event.AgentEvent> sendStream(String peerId, String text)
      Streaming variant of send(String, String).
    • sendStream

      public reactor.core.publisher.Flux<io.agentscope.core.event.AgentEvent> sendStream(SendOptions options, String text)
      Streaming variant of send(SendOptions, String).
    • sendToSubagentStream

      public reactor.core.publisher.Flux<io.agentscope.core.event.AgentEvent> sendToSubagentStream(String subagentId, String text)
      Streaming variant of sendToSubagent(String, String).
    • sendStream

      public reactor.core.publisher.Flux<io.agentscope.core.event.AgentEvent> sendStream(ChatUiRequest request)
      Streaming variant of send(ChatUiRequest).