Skip to content

symfonic.core.prompt.caching

caching

Anthropic prompt caching support: CacheBlock and CacheablePrompt.

CacheBlock dataclass

CacheBlock(
    type: str = "text",
    text: str = "",
    cache_control: dict[str, str] | None = None,
    cache_ttl: CacheTtl | None = None,
)

A content block with optional cache_control annotation.

Matches the Anthropic API content block format. Set cache_control to {"type": "ephemeral"} to mark the block for server-side caching.

Attributes:

Name Type Description
type str

Content block type. Always "text" for the v7.x cached system-prompt path; "image" / future block types pass through transparently.

text str

Rendered body.

cache_control dict[str, str] | None

When non-None, the block is advertised as cached. The marker emitted on the wire depends on cache_ttl. When None the block is uncached and cache_ttl is ignored.

cache_ttl CacheTtl | None

v7.24.0 NEW — optional TTL hint when this block is cached. None (default) preserves v7.23 byte-for-byte: the wire-level marker is the bare {"type":"ephemeral"} 5-minute default. "5m" is an explicit-intent alias for the same wire shape (useful for callers that want intent in code). "1h" flips the marker to {"type":"ephemeral","ttl":"1h"} which Anthropic honours as the 1-hour tier on Sonnet / Haiku / Opus families that support it. Setting cache_ttl while cache_control is None is a no-op (the block stays uncached). See docs/concepts/cache-tier-tradeoffs.md for the cost-vs-cache analysis.

CacheablePrompt dataclass

CacheablePrompt(blocks: tuple[CacheBlock, ...] = ())

A prompt assembled with Anthropic cache_control annotations.

Used when the caller wants cache-annotated output from PromptBuilder.build_cached(). Content is structured as a tuple of CacheBlock instances rather than a single string, matching the format Anthropic expects for system prompt blocks.

to_anthropic_content

to_anthropic_content() -> list[dict[str, Any]]

Convert to the Anthropic API system-prompt content list format.

Each block becomes a dict with at minimum type and text. When a block participates in caching, cache_control is included; the marker is shaped per CacheBlock.cache_ttl via :func:_serialise_cache_marker.

Source code in src/symfonic/core/prompt/caching.py
def to_anthropic_content(self) -> list[dict[str, Any]]:
    """Convert to the Anthropic API system-prompt content list format.

    Each block becomes a dict with at minimum ``type`` and ``text``.
    When a block participates in caching, ``cache_control`` is
    included; the marker is shaped per ``CacheBlock.cache_ttl`` via
    :func:`_serialise_cache_marker`.
    """
    result: list[dict[str, Any]] = []
    for block in self.blocks:
        entry: dict[str, Any] = {"type": block.type, "text": block.text}
        marker = _serialise_cache_marker(block.cache_control, block.cache_ttl)
        if marker is not None:
            entry["cache_control"] = marker
        result.append(entry)
    return result

to_plain_text

to_plain_text() -> str

Fallback: join all non-empty text blocks with double newlines.

Source code in src/symfonic/core/prompt/caching.py
def to_plain_text(self) -> str:
    """Fallback: join all non-empty text blocks with double newlines."""
    return "\n\n".join(b.text for b in self.blocks if b.text)