Skip to content

Adding agent session, streaming chunk and task/plan block support - #262

Merged
soxtoby merged 4 commits into
soxtoby:masterfrom
we4sz:agent-sessions-and-streaming
Oct 13, 2026
Merged

soxtoby merged 4 commits into
soxtoby:masterfrom
we4sz:agent-sessions-and-streaming

Conversation

@we4sz

@we4sz we4sz commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Slack's newer agent features (sessions with a status and a Stop button, streamed task and plan updates, task and plan blocks) have no SlackNet support yet. This adds it in four commits. Each one builds and passes the tests.

  1. TaskCardBlock, PlanBlock and UrlSourceElement: the task_card and plan blocks, and the sources a task can cite.
  2. AgentsSessionsApi.SetStatus for agents.sessions.setStatus, exposed as ISlackApiClient.AgentsSessions, with AgentSessionStatus and AgentSessionStatusResponse.
  3. The AgentSessionStopped event (agent_session_stopped), which Slack sends when a user presses the Stop button.
  4. New optional parameters on ChatApi.StartStream, AppendStream and StopStream: chunks (StreamChunk: markdown text, task update, plan update, blocks), taskDisplayMode, sessionStatus, and the iconEmoji, iconUrl and username overrides on start. AppendStream's markdownText is optional now, since a chunk stream has none.

Compatibility

Nothing changes meaning. The new parameters are optional and sit before cancellationToken, so existing code compiles unchanged. A caller built against an older SlackNet binary has to be rebuilt.

Testing

The unit tests follow the existing patterns: request bodies, JSON round trips, event deserialization, and ApiLintTests and BlockLintTests extended for the new types. One existing test, UtilsTests.ToDateTime_FromTimestampString_ValidTimestamp_ReturnsDateTime, fails on an untouched v0.18.0 here, before and after these changes.

I also ran the changes against a real Slack app in a real workspace:

  • Streaming: start, append and stop with every chunk type, both task_display_mode values and session_status; sources, icons and hide_title; and the streaming_mode_mismatch error.
  • Blocks: standalone plan and task_card messages. They render, and Slack's read-back returns the same block types.
  • agents.sessions.setStatus: request and response against an app in agent mode, processing then active. The response is {ok, status, agent_status, title}, which AgentSessionStatusResponse matches. Before the app was declared an agent, the same call answered not_authorized. The call needs only the chat:write scope.
  • Stop button: while a session was processing and the app was subscribed to agent_session_stopped, Slack showed its native Stop button, and a user pressed it.

Not verified: the payload of agent_session_stopped. I couldn't capture the event in my test setup, so AgentSessionStopped follows the documentation only.

What the documentation doesn't say

Found while testing:

  • A markdown_text chunk is sent with the key text. Slack rejects markdown_text as the key.
  • A message can't contain both a plan block and task_card blocks (invalid_blocks). blocks.validate accepts such a message.
  • pending is accepted for tasks in a plan block and in streamed task updates. A standalone task_card rejects it.
  • A task's icon is the name of one of a fixed list of icons, not a URL, so it is a string here.
  • agents.sessions.setStatus stored my title with the : replaced by _ ("Dispatch probe: agent session status" came back as "Dispatch probe_ agent session status"). The title is only applied when the session is created, as documented.

@soxtoby

soxtoby commented Oct 13, 2026

Copy link
Copy Markdown
Owner

Thanks @we4sz, looks solid. Will get a release out later this week with these changes.

@soxtoby
soxtoby merged commit eb324eb into soxtoby:master Oct 13, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants