Agentic contentediting framework
A content-agnostic agentic editing system built on LangGraph and dependency injection. New content types plug in via config alone. The 3-phase split-execution pipeline decouples low-latency SSE streaming from LangGraph's node-update model, while targeted LLM edits replace full-document regeneration and cut token consumption by ~60%.
The problem
The platform needed AI-powered editing across multiple content types: structured tables, markdown documents, bullet lists. The naive approach was full-document regeneration on every edit, which was wasteful, slow, and prone to silent rewrites that changed content the user hadn't touched.
Adding a new content type required touching core graph nodes. The system was tightly coupled to its first content format, and every new type was a fork of existing logic.
The architecture
A 3-phase split-execution pipeline. Phase 1 (setup graph) resolves the content type and classifies intent using heuristic keyword/modifier matching, deferring to the LLM only on ambiguous inputs. Phase 2 runs token-level streaming via SSE. Phase 3 runs a validation graph with auto-retry on malformed output.
# phase 1: heuristic intent classification
def classify_intent(op, content_type):
if keyword_match(op):
return resolve_modifier(op)
return llm_classify(op, content_type) # LLM fallback
# phase 2: token-level SSE stream
async def stream_edit(graph, op):
async for tok in graph.stream(op):
yield f'data: {tok}\n\n'
# phase 3: validate + auto-retry
await validation_graph.run(result)Dependency injection lets new content types register via configuration with zero changes to core graph nodes. A targeted-operations protocol (edit, split, delete, insert) replaces full-document regeneration while preserving untouched content verbatim.
Details that mattered
- Partial-output continuation: detects truncated JSON via item-count vs. schema completeness, narrows the target range, and reissues a continuation prompt with prior output as tonal anchor.
- Word-level diffs: difflib.SequenceMatcher producing per-field, position-aligned change spans. Removed words are struck through in red, additions highlighted in green.
- Length preservation: prompt-level per-item character/word counts with ±20% guardrails prevented detail loss during model edits.
- Multi-turn refinement: conversation-history accumulation so models received full context across iterative edits.
- Resilient JSON parsing: fence stripping, bracket repair, and regex fallback extractors for malformed or truncated outputs across multiple LLM providers.