agentleFS
lauren-frameworklauren-framework/lauren-ai/skills/streaming-response-handler/SKILL.md

streaming-response-handler

Skill0 starsChanged 6 months agoMITView on GitHub

Streams LLM responses chunk-by-chunk from an agent via runner.run_stream(). Use when building real-time UIs, SSE endpoints, WebSocket streaming, or any feature that needs to display tokens as they arrive rather than waiting for the full response.

The file

Files
SKILL.md

Use codemap find "SymbolName" to locate any symbol before reading — it gives exact file + line range and is faster than grep across the whole repo.

Streaming Response Handler

Quick start

# from __future__ import annotations is safe here (no @tool definitions)
from __future__ import annotations

from lauren_ai._agents._runner import AgentRunnerBase as AgentRunner
from lauren_ai._config import LLMConfig
from lauren_ai._transport._mock import MockTransport

cfg = LLMConfig(provider="anthropic", model="claude-opus-4-6", api_key="sk-ant-...")
runner = AgentRunner(transport=transport)

async for chunk in await runner.run_stream(my_agent_instance, "Tell me a joke"):
    if chunk.delta:
        print(chunk.delta, end="", flush=True)
    if chunk.stop_reason:
        print()  # newline at end

CompletionChunk fields

FieldTypeDescription
deltastrText fragment from this chunk (may be empty string)
stop_reasonstr | NoneSet on the final chunk: "end_turn", "tool_use", etc.
usageTokenUsage | NoneSet on the final chunk with token counts
thinking_deltastr | NoneAnthropic extended thinking fragment
tool_call_deltaToolCallDelta | NoneStreaming tool-call fragment
guardrail_overridestr | NoneSet if a guardrail replaced the output

Accumulate full text

async def stream_and_collect(runner, agent_instance, prompt):
    full_text = ""
    async for chunk in await runner.run_stream(agent_instance, prompt):
        if chunk.delta:
            full_text += chunk.delta
    return full_text

Lauren SSE integration

from lauren import sse, EventStream
from lauren_ai._agents._runner import AgentRunnerBase as AgentRunner

@get("/chat/stream")
async def chat_stream(
    prompt: Query[str],
    agent: MyAgent,
    runner: AgentRunner,
) -> EventStream:
    async def _generate():
        async for chunk in await runner.run_stream(agent, prompt):
            if chunk.delta:
                yield chunk.delta

    return EventStream(_generate())

Testing pattern — queue stream chunks

from lauren_ai._transport import CompletionChunk, TokenUsage
from lauren_ai._transport._mock import MockTransport

mock = MockTransport()
mock.queue_stream([
    CompletionChunk(delta="Hello"),
    CompletionChunk(delta=" world"),
    CompletionChunk(
        stop_reason="end_turn",
        usage=TokenUsage(input_tokens=5, output_tokens=2),
    ),
])

chunks = []
async for chunk in await runner.run_stream(my_agent, "hi"):
    chunks.append(chunk)

Reference files

FileContents
src/lauren_ai/_agents/_runner.pyrun_stream() implementation
src/lauren_ai/_transport/__init__.pyCompletionChunk, ToolCallDelta
src/lauren_ai/_transport/_mock.pyqueue_stream() helper

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.