Treat the Context Window as a Data Assembly Problem

tank-341 pts0 comments

Treat the Context Window as a Data Assembly Problem - Pydantic-resolve

Skip to content

Advanced

API Reference

Reference

Articles

Redefinition: LLM context = response tree

Mechanism mapping

Walkthrough: a customer support agent context

Comparison with other approaches

One Entity graph, four consumer types

When to use it, when not to

Conclusion

Redefinition: LLM context = response tree

Mechanism mapping

Walkthrough: a customer support agent context

Comparison with other approaches

One Entity graph, four consumer types

When to use it, when not to

Conclusion

Treat the Context Window as a Data Assembly Problem: Where pydantic-resolve Fits in AI Workflows

A typical piece of AI code

Open any service in your project that calls an LLM. You will most likely see a function that looks something like this:

async def build_support_context(ticket_id: int) -> str:<br>ticket = await db.get(Ticket, ticket_id)<br>customer = await db.get(Customer, ticket.customer_id)

recent_tickets = await db.query(Ticket).filter(<br>Ticket.customer_id == customer.id<br>).order_by(Ticket.created_at.desc()).limit(5).all()

# Retrieve similar past tickets<br>embedding = await embed(ticket.description)<br>similar = await vector_store.search(embedding, top_k=3)

# Each similar ticket needs its resolution pulled in<br>similar_with_resolution = []<br>for s in similar:<br>resolution = await db.query(Resolution).filter(<br>Resolution.ticket_id == s.id<br>).first()<br>similar_with_resolution.append({<br>"title": s.title,<br>"resolution": resolution.text if resolution else "",<br>})

# Collect tags<br>all_tags = []<br>for t in recent_tickets:<br>all_tags.extend(t.tags)

# Finally, ask the LLM to summarize<br>summary = await llm.summarize(<br>customer=customer,<br>recent_tickets=recent_tickets,<br>similar=similar_with_resolution,

return f"""<br>Customer: {customer.name} (id={customer.id})<br>Recent tickets: {len(recent_tickets)}<br>Tags: {', '.join(set(all_tags))}<br>Similar past cases:<br>{format_similar(similar_with_resolution)}<br>Summary: {summary}<br>"""

The function is not long, but the problem is already visible: this is a build_context() function that is fundamentally doing data assembly, but its shape is entirely procedural .

It is isomorphic to the FastAPI code that Clean Architecture for Python criticizes — only "assembling an API response" has been swapped for "assembling a prompt context". The problems are unchanged:

Data-fetching logic is scattered through the function body with no structure.

Dependencies of derived fields (all_tags, summary) are held together by comments and line ordering.

Vector retrieval, database queries, and LLM calls live in one function. Every new piece of context means editing this function.

Concurrency optimization (fetching similar tickets in parallel) requires a rewrite.

Reuse — say, exposing recent_tickets to the frontend too — is impossible.

This code is not badly written. It has no home .

"The context window" is a data assembly problem

When people discuss LLM applications, attention usually lands first on prompt templates, model choice, and temperature. Those matter — but as applications grow, the real bottleneck shifts from prompt engineering to context assembly .

The reason: prompt templates are stable, model choice is stable, but "what data to feed the LLM" differs on every call . A support agent handling ticket A and ticket B can share the same prompt template, yet the underlying data-assembly path may diverge completely — A is a VIP customer requiring SLA context and similar-case retrieval; B is a regular customer needing only the basics.

This "same template, different data-assembly path" requirement is exactly what API response assembly does . Your FastAPI project already solves it — different endpoints assemble different response trees. An LLM context is just another endpoint, only the consumer is an LLM rather than an HTTP client.

Once that perspective lands, the problem becomes concrete. The things pydantic-resolve solves well on the API side hold equally well on the LLM side:

API response assembly<br>LLM context assembly

Multi-level nesting (Sprint → Task → Owner)<br>Multi-level nesting (Customer → Ticket → Similar Ticket)

Batch-load related data<br>Batch-recall related context

Derived fields (task_count, contributors)<br>Derived context (summary, aggregated_tags)

N+1 database queries<br>N+1 vector retrievals + N+1 LLM calls

Cross-subtree aggregation (deduplicate all owners)<br>Cross-subtree aggregation (merge evidence across similar tickets)

Every item in the right column already has a solution on the left. We only need to bring the same machinery over.

Three classic assembly pain points

Breaking the build_support_context snippet apart reveals three symptom classes. They are not specific to support scenarios — they recur in nearly every LLM application.

Pain point 1: N+1 LLM calls

for s in similar:<br>resolution = await db.query(Resolution).filter(...).first()

This is a classic N+1 on the ORM side. In the LLM world it gets worse — you might be calling...

context customer assembly ticket similar data

Related Articles