Skip to content

feat(runtime): expose typing-indicator control for runtime-token agents#298

Closed
samxu01 wants to merge 1 commit intomainfrom
sam/agent-typing-runtime-endpoint
Closed

feat(runtime): expose typing-indicator control for runtime-token agents#298
samxu01 wants to merge 1 commit intomainfrom
sam/agent-typing-runtime-endpoint

Conversation

@samxu01
Copy link
Copy Markdown
Contributor

@samxu01 samxu01 commented May 4, 2026

Summary

Adds POST /api/agents/runtime/pods/:podId/typing — runtime-token agents (CLI wrappers, webhook bots, external SDK clients) can now emit agent_typing_start / agent_typing_stop over Socket.io, getting the same conversational chrome as native cloud agents.

Body: { action: 'start' | 'stop' } (defaults to 'start')

Why this exists

nativeRuntimeService and agentEventService already emit typing_start when they enter the agent loop, and the existing POST /messages handler emits typing_stop on message land via agentMessageService.postMessage. But there's no symmetric typing_start hook for external agents — so their messages appear instantly with no '…' pre-roll while native ones get the expected fade-in.

This route closes that gap. With it, an external agent (CLI-wrapped or webhook) can:

```
POST /pods//typing {action: 'start'} # show the typing indicator
sleep 1.2s
POST /pods//messages {content: '...'} # auto-emits typing_stop on land
```

Safety

  • Same auth (agentRuntimeAuth) and pod authorization (ensurePodMatch) as the existing POST /messages handler.
  • Same rate limit (phase4RateLimit).
  • Existing 30s auto-clear in agentTypingService prevents stuck indicators if a caller forgets to call stop or crashes between start and message land.
  • agentMessageService.postMessage emits typing_stop on every message land — so the typical pattern is fire-and-forget the start; the message itself stops the indicator.

Identity resolution

displayName + avatar are resolved via AgentIdentityService.getOrCreateAgentUser — same chain agentEventService uses. User.botMetadata.displayName wins over installation.displayName, falls back to agentName. avatar comes from User.profilePicture.

Test plan

  • tsc --noEmit clean
  • Smoke after deploy: curl -X POST .../pods/<id>/typing from a CLI-wrapped agent emits agent_typing_start over WS; subsequent POST /messages clears it
  • Demo recording uses this for Cody, Pixel, and Nova fallback messages so the multi-vendor handoff at beat 3 has the conversational pre-roll

🤖 Generated with Claude Code

Adds POST /api/agents/runtime/pods/:podId/typing — runtime-token agents
can now emit agent_typing_start / agent_typing_stop, getting the same
conversational chrome as native cloud agents.

Body: { action: 'start' | 'stop' }  (defaults to 'start')

Why this exists
---------------
Internal callers (nativeRuntimeService, agentEventService) auto-emit
typing_start when they enter the agent loop and typing_stop on message
land. agentMessageService emits typing_stop when an external agent's
POST /messages lands — but never typing_start. Net effect: external
agent messages appear in chat instantly with no '…' pre-roll, while
native ones get the expected conversational fade-in.

This route closes that gap. CLI wrappers (ADR-005), webhook bots
(ADR-006), and demo drivers can now POST {action:'start'} ~1s before
their content message and the message lands with proper chat chrome.

Safety
------
- 30s auto-clear in agentTypingService prevents stuck indicators if a
  caller forgets stop or crashes between start and message land
- Existing agentMessageService.postMessage emits typing_stop on land,
  so callers can fire-and-forget the start (the message itself stops
  the indicator)
- Same auth (agentRuntimeAuth) + pod authorization as POST /messages
- Same rate-limit (phase4RateLimit)

Identity
--------
displayName + avatar resolved via AgentIdentityService.getOrCreateAgentUser
the same way agentEventService does — User.botMetadata.displayName wins
over installation.displayName, falls back to agentName.

Driver pattern
--------------
  send_with_typing(podId, agent, msg) {
    POST /pods/$podId/typing  {action: 'start'}
    sleep 1.2s
    POST /pods/$podId/messages {content: msg}  // auto-emits typing_stop
  }
samxu01 added a commit that referenced this pull request May 4, 2026
…ts (#298)

Adds POST /api/agents/runtime/pods/:podId/typing — runtime-token agents
get the same conversational chrome as native cloud agents.

Body: { action: 'start' | 'stop' }

agentMessageService.postMessage already emits typing_stop on message
land, so the pattern is: POST /typing {start} → sleep ~1.2s → POST
/messages. 30s auto-clear in agentTypingService prevents stuck
indicators if a caller crashes between start and message land.

Same auth + pod authorization + rate limit as POST /messages. Identity
resolution mirrors agentEventService — User.botMetadata.displayName +
User.profilePicture for the typing payload.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@samxu01 samxu01 closed this May 4, 2026
@samxu01 samxu01 deleted the sam/agent-typing-runtime-endpoint branch May 4, 2026 07:16
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.

1 participant