mcpField
N
ns-langgraph-agents

ns-langgraph-agents

github.com/nextstage-brasilAgent workflows0154 installsUpdated 1w ago
Repository

About ns-langgraph-agents

ns-langgraph-agents is a skill for building and maintaining LangGraph.js agent runtimes with TypeScript. It provides guidance on runtime layout, prompt and capability injection, MCP governance, and keeping graph specifications aligned with runtime changes.

Key features

  1. 01LangGraph.js runtime guidance
  2. 02Agent file placement rules
  3. 03Prompt and capability injection
  4. 04MCP access governance references
  5. 05Graph-spec synchronization gates

Use cases

  1. 01Bootstrap a new LangGraph agent runtime
  2. 02Recover an unclear existing runtime layout
  3. 03Plan prompt or tool binding changes
  4. 04Update graph specifications with runtime changes

MCP support

It guides agent implementations that use MCP tools as capabilities within a LangGraph graph. References cover multi-server MCP discovery, transport, lifecycle, allowlists, and tool budgets.

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/nextstage-brasil/skills --skill ns-langgraph-agents

After installing, type/ns-langgraph-agentsin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

evals/
evals.json
references/
anti-patterns-extended.md
anti-patterns.md
architectures.md
bootstrap-agent-runtime.md
capability-governance.md
context-window-and-tokens.md
error-and-reliability.md
evals-and-gates.md
evidence-and-fidelity.md
guardrail-and-adversarial.md
mcp-complex-access.md
message-content-blocks.md
model-cascade-and-cache.md
observability.md
orphan-recovery-checklist.md
placement-and-domains.md
prompt-and-capability-injection-plan-execute.md
prompt-and-capability-injection.md
runtime-layout.md
streaming-and-hitl.md
turn-flow-gates.md
user-memory.md
scripts/
bootstrap-agent-runtime.mjs
templates/agent-runtime/
.dockerignore
.env.example
.gitignore
docker-compose.yml
Dockerfile
templates/agent-runtime/config/
README.md

Details

From the project README

LangGraph Agents

Production-grade LangGraph.js (Node 24+, TypeScript strict, @langchain/langgraph).

Owns runtime doctrine — placement, prompt/capability injection, graph-spec sync. Diffs via ns-coder or ns-autonomous. Framework choice: ns-agent-architecture.

Applicability

ContextDoctrine strength
Greenfield agent-api (new LangGraph runtime)MUST follow build workflow gates — dev-chat, budgets, normalize-before-truncate, separate skill cap. Topology: suggest plan_execute for most MCP/tool-heavy cases — lock in graph-spec.md; not a hard rule
Brownfield existing agentRECOMMENDED migration toward same controls; orphan recovery does not Critical-fail missing topology
Intentional MCP redesignSync graph-spec.md + refs in same delivery — treat greenfield MUST for topology/budget/evidence sections touched

Brownfield open ReAct valid until deliberate topology change. Greenfield MUST = new agent-api + intentional MCP redesign only.

Routing (read first)

SignalAction
Conceptual design unlocked (agent vs RAG vs fine-tune)Stop → ns-agent-adaptation
No framework lock / CrewAI requestedStop → ns-agent-architecture
Orphan / lost structure / layout unclearRun orphan checklist before features (references/orphan-recovery-checklist.md)
GitLab ISSUE_URL or SDD version scopeDefer to harness ../../ns-harness/references/code-skill-routing.md — do not absorb
Approved placement/inject plan ready for diffHand off to ns-coder for implementation — except greenfield bootstrap copy (references/bootstrap-agent-runtime.md)

Boot (mandatory)

See ../../ns-harness/references/session-boot.md — complete Session boot (blocking) there, then:

  1. Confirm {agent_api_root} and graph-spec.md when touching runtime
  2. Load placement/inject refs before path decisions (references/placement-and-domains.md, references/prompt-and-capability-injection.md)
  3. Continue this skill

Success: placement + inject doctrine + project rules. Failure: invented folders or external frameworks.

When to use

SituationAction
Greenfield agent-api (no {agent_api_root}/package.json)Build workflow Phase 0 then Phase 1 bootstrap — references/bootstrap-agent-runtime.md
Brownfield / orphaned runtimeRun Orphan recovery (references/orphan-recovery-checklist.md) before features
New file / unclear folderPlacement Decision Block + references/placement-and-domains.md
System prompt / skill inject / bindPrompt/Capability plan + references/prompt-and-capability-injection.md
Topology / state / capabilities / guard_fail_mode changeSpec Sync Gate — update graph-spec.md in the same delivery
MCP with many servers/toolsRead references/mcp-complex-access.md + references/capability-governance.md
Token blow-up / slow turnsRead references/context-window-and-tokens.md
Agent must remember the user (preferences, terms, CRUD)Read references/user-memory.md — per-user store, deduce-and-inform, /memories routes
Untrusted input / injection / claimed authorityRead references/guardrail-and-adversarial.md — scope classifier; scaffold fail-open ≠ doctrine
Cost-sensitive high volume / model tier / cacheRead references/model-cascade-and-cache.md
Provider message/reasoning quirksRead references/message-content-blocks.md
HITL / streaming UXRead references/streaming-and-hitl.md
JSON planner / analyst chooses toolsOperator-progress channel — templates/contracts/planner-contract.md + references/streaming-and-hitl.md
Prompt change / repeated hops / loop / "fixed" claimRead references/turn-flow-gates.md — flow-first, terminal, repetition, evidence gates
Evals before mergeRead references/evals-and-gates.md

Core doctrine

LangGraph = control flow. MCP/local tools = capabilities under graph. Small graph state (refs, summaries). Checkpointer = full state; context window = LLM view — separate.

System prompt: compose base_invariant (motor) + injected (product persona) per LLM invoke. Never persist composed system/persona text in graph state, checkpointer, or durable messages. Summary SystemMessage at index 0 ≠ full system — references/prompt-and-capability-injection.md, references/message-content-blocks.md.

Locale: conversation-observed turnLocale (detection-first from human messages ± intent slots); configurable.locale weak hint only; Intl formatters in code — not fixed bootstrap locale. references/evidence-and-fidelity.md, templates/snippets/conversation-locale.ts.snippet.

Operator progress (JSON planner hops): greenfield streaming_sse with a planner/analyst that emits structured executionPlan (no bindTools on that hop) MUST persist userFacingIntent (or analysis.userFacingIntent) + executionPlan on AgentState. userFacingIntent language MUST match the current user message (last HumanMessage) — not English unless that message is English; not product default locale. Machine intent stays English for audit. Emit SSE thinking from that field at node entry of the next hop — not response_streaming, not in durable messages. Hop 0 uses generic copy from conversation/presentation/ (or locale) in the same operator language. Open ReAct + ToolNode uses tool_started / tool_finished only. Details: templates/contracts/planner-contract.md, references/streaming-and-hitl.md.

Three capability kinds bind to the model:

KindLLM wire nameInternal id
Local tool{name}local:{name}
MCP toolmcp__{server}__{tool}mcp:{server}:{tool}
Skill procedureuse_skill__{id}skill:{id}

Wire names must match ^[a-zA-Z0-9_-]{1,128}$ (use __ separators; colons only in internal ids). Colon in a new wire name is Critical on review.

Pre-change gates

Before new file or inject/bind change: complete all three. No code until posted.

1. Placement Decision Block
### Placement Decision Block

- Artifact: …
- Type: …
- Target path: …
- Layer: …
- Refs: placement-and-domains.md
- do_not_create_under: […]

Full matrix: references/placement-and-domains.md.

2. Prompt / Capability plan
### Prompt / Capability plan

- Compose: base_invariant + injected (rebuild per invoke; not in state/checkpointer/durable messages)
- Motor (`base_invariant`): [gather-no-Markdown / sole-writer / tool discipline / JSON planner userFacingIntent is SSE not Markdown / …]
- Product (`injected`): canonical path + persona/tone notes; mode-resolved: yes/no; modes: [...]; resolver: ...
- System layers touched: […]
- Canonical prompt path: …
- Session overlay: yes/no
- Bind list: […]
- Auto-inject skills: […] (exclusive of bind for same id)
- Truncate caps: tool vs skill body
- Bind parity: …
- Spec paths to sync: […]

Full doctrine: references/prompt-and-capability-injection.md. Plan/mode-resolve: references/prompt-and-capability-injection-plan-execute.md.

3. Spec Sync Gate

Nodes, edges, state, capabilities, recursion_limit, wire names, or guard_fail_mode change: update graph-spec.md same delivery. Stale archive ≠ SoT — sync spec to intended runtime; do not force-fit live code to stale archive.

Reference map

Load on demand — do not memorize whole files.

ReferenceRead when
references/bootstrap-agent-runtime.mdGreenfield copy of templates/agent-runtime/
references/orphan-recovery-checklist.mdProject structure unclear or agent "lost"
references/runtime-layout.mdScaffolding, refactors, layer violations
references/placement-and-domains.mdWhere to put files; domain vs graph vs config
references/prompt-and-capability-injection.mdSystem prompt layers, bind vs inject, bind parity
references/prompt-and-capability-injection-plan-execute.mdPrompt/Capability plan; plan_execute gather vs composer; mode-resolved injected
references/message-content-blocks.mdAIMessage/HumanMessage/ToolMessage across providers
references/context-window-and-tokens.mdtrim, summarize, tool vs skill body caps, context_manager
references/mcp-complex-access.mdMulti-server MCP, discovery, transport, lifecycle
references/capability-governance.mdAllowlist, classification, rate limits, tool budgets
references/evidence-and-fidelity.mdState-backed evidence, fidelity gate, conversation-observed locale
templates/snippets/conversation-locale.ts.snippetresolveConversationLocale + Intl formatUserFacing
templates/snippets/tool-budget.ts.snippetPer-turn tool/MCP caps, arg fingerprint duplicate-skip
templates/snippets/prepare-llm-messages.ts.snippetcontext_manager helper
references/error-and-reliability.mdTool errors, circuit breaker, retries, compensation, parallel staleness, cost stop
references/model-cascade-and-cache.mdCheap-first cascade, both signals OR-escalate, semantic/prompt cache; not LLM intent_classify hop
references/observability.mdPostgres audit, retention = tenant clock, query tenant+period+one decision, cost reservation
references/architectures.mdReAct, plan_execute (suggested start for most MCP), Reflection levels, other topologies; node id ≠ state channel
references/guardrail-and-adversarial.mdScope/safety classifier; fail-open scaffold ≠ graph-spec lock; not Gateway routing
references/streaming-and-hitl.mdSSE envelopes, operator thinking, interrupted, resume SSE, interrupt(), Command resume
references/turn-flow-gates.mdPrompt/loop incidents: flow-first, terminal, repetition, tool-error, DoD
templates/contracts/planner-contract.mdJSON planner hops: executionPlan + userFacingIntent
references/user-memory.mdPer-user long-term memory: kinds, deduce-and-inform write path, per-invoke read, /memories CRUD, LGPD
references/evals-and-gates.mdArchitecture, tool-selection, memory evals; golden-set promotion
references/anti-patterns.mdReview gate before marking done — hot path
references/anti-patterns-extended.mdDead prompt copies, state/memory, reliability, graph, MCP, LLM, ops, process

Templates: templates/agent-runtime/ (greenfield tree), templates/graph-spec.md, templates/contracts/, templates/snippets/ (brownfield patches).

Session inputs

VariableRequired
{agent_api_root}Default agent-api
{task}What to build, fix, or review

Orphan recovery (brownfield first)

Runtime disorganized or team blocked:

  1. Read references/orphan-recovery-checklist.md; score project.
  2. Gap report: structure, placement, context window, inject/bind parity, MCP governance, HTTP, spec sync.
  3. Ordered fix plan (one phase per message if large).
  4. Implement via ns-coder.

No new graph nodes or MCP servers until layout + governance baselines pass.

Build workflow (greenfield or post-recovery)

Phase 0 — Spec gate

If graph-spec.md is missing, create it from templates/graph-spec.md. Minimum sections: locked header (framework, architecture, interaction_mode, guard_fail_mode), domain ownership, prompt composition, state schema, nodes table, edges, interrupts, memory, capability bind/inject table, recursion_limit, HTTP routes.

If the user has no architecture decision yet, stop and invoke ns-agent-architecture first.

Phase 1 — Skeleton

If {agent_api_root}/package.json is missing, run scripts/bootstrap-agent-runtime.mjs (references/bootstrap-agent-runtime.md). Then npm install && npm test in {agent_api_root}.

Do not assemble the tree from templates/snippets/. Do not copy another product. After copy: align src/graph/ with graph-spec.md; put domain in conversation/ + config/ via later phases / ns-coder.

Brownfield existing tree: align per references/runtime-layout.md — snippets for patches only.

Phase 2 — State and persistence

After bootstrap, verify these exist; do not re-scaffold. Fill only gaps vs graph-spec.md.

  • AgentState with messages reducer (Annotation.Root or Zod + MessagesZodMeta).
  • PostgresSaver in dev/prod; MemorySaver only in tests/setup.ts.
  • Long-term memory (when graph-spec.md locks it): per user (tenant_id + user_id), never per thread_id — references/user-memory.md.
  • Every invoke/stream: configurable.thread_id via buildRunConfig.
  • JSON planner/analyst (no bindTools on that hop): declare executionPlan + userFacingIntent (or nested on analysis) in graph-spec.md state schema — templates/snippets/state.ts.snippet.
Phase 3 — LLM and messages
  • Provider config in src/llm/ (infra only — no domain prompts).
  • One env var per model role (e.g. chat, summarize, embed) — no hardcoded model id in source.
  • Embedding model change invalidates vector index → full re-seed required.
  • Graph/node unit tests: fake LLM in default tier. Prompt/guardrail behavior needing a real model → live tier (Test tiers in ns-harness → docker-and-testing.md).
  • Prefer JSON mode + Zod parse for structured turns; avoid withStructuredOutput on OpenAI-compatible local servers.
  • Normalize provider output via contentBlocks / content_blocks — see references/message-content-blocks.md.
Phase 4 — Context window (mandatory)

Implement per references/context-window-and-tokens.md:

  • trimMessagesForLlm before every LLM call.
  • normalizeMcpToolResult then truncateToolOutput before ToolMessage enters state.
  • Separate CONTEXT_SKILL_BODY_MAX_CHARS for skill bodies (snippet skillBodyMaxChars).
  • Summarize when used tokens exceed 80% of CONTEXT_MAX_TOKENS (raw window). Ratios are constants: trigger 0.8, compact to 0.5, summary cap 0.1. No summarize multiplier env.
  • summarizeOlderMessages with persisted compaction (RemoveMessage + rewrite) in the same agent-node return.

Never pass raw state.messages to the model.

Phase 5 — Capabilities
  1. Local StructuredTools in src/tools/.
  2. MCP: governed client — discovery → local allowlist → wire names → singleton client lifecycle (references/mcp-complex-access.md).
  3. Skills: skills/*.md auto-discovered → use_skill__{id} or auto-inject (exclusive per id).

Apply references/capability-governance.md and references/prompt-and-capability-injection.md before bindTools. Enforce bind parity. Wire per-turn tool/MCP budgets from templates/snippets/tool-budget.ts.snippet when MCP or external tools are bound.

Phase 6 — HTTP and interaction mode
ModeRequirements
sync_jsonPOST /threads, POST /threads/:id/message
streaming_sseSSE envelope per references/streaming-and-hitl.md; composer reply MUST model.stream() + cumulative response_streaming ticks (not invoke-dump); SSE flush leave-now; dev-chat flushSync per tick; greenfield MUST ship styled React GET /dev-chat (DEV_CHAT_ENABLED, local-only) + GET /dev-chat/app.js; JSON planner hops MUST emit operator thinking; Docker artifacts (Dockerfile, agent-only compose) shipped
HITLinterrupt() + POST /threads/:id/resume (SSE when Accept SSE) with Command({ resume }); always-escalate MUST send approver_id + approver_role; paused graph → terminal interrupted

User memory enabled → caller-scoped /memories CRUD (references/user-memory.md §5); user_id from auth only.

Brownfield missing dev-chat: recommend add — not Critical. Postman synced with live routes.

Phase 7 — Observability

Wire references/observability.md: initDb, runStorage, logLlmCall, logToolExecution, persist turn_decisions. LangSmith and OTel are opt-in.

Phase 8 — Evals and review
  • Add suites per references/evals-and-gates.md.
  • Run npm run build && npm test in {agent_api_root}.
  • Invoke ns-reviewer on the diff; ask it to verify placement, inject, wire-name, and bind-parity anti-patterns when the diff touches agent-api.

Maintenance workflow

Ongoing work (not greenfield):

  1. Three Pre-change gates
  2. graph-spec.md matches intended graph after change
  3. Layer: graph node, conversation, MCP, memory, HTTP
  4. Read matching reference before edit
  5. Minimal diff via ns-coder with placement/inject handoff
  6. Postman on HTTP route change
  7. Re-run orphan checklist items touched

MCP complex access (quick rules)

Multiple MCP servers, overlapping or large catalogs:

  • Discovery filter — allowlisted tools/list before bind
  • Local classify — read | write | destructive | admin; never trust server read-only flags
  • Singleton client — one MultiServerMCPClient per process; no per-request stdio in prod
  • Transport — Streamable HTTP deployed; stdio local single-user dev only
  • Errors — MCP isError: true = recoverable ToolMessage status: "error"; protocol fail may abort with HTTP/SSE failed
  • Secrets — env or configurable / request payload only; never state or checkpointer

Full: references/mcp-complex-access.md.

Handoff to ns-coder

When implementation is approved, delegate with:

## LangGraph implementation task

- Root: {agent_api_root}
- Spec: path/to/graph-spec.md
- Phase: [number and name from this skill]
- target_paths: […]
- layer: […]
- do_not_create_under: […]
- injection_notes: [layers / bind vs auto-inject / caps]
- spec_paths_to_sync: […]
- References to apply: [list]
- Acceptance: build + test pass; orphan checklist items [n] resolved; placement + inject + bind parity verified
- Review: ns-reviewer after tests — must check placement, inject, wire names (`:`), bind parity (load ns-langgraph-agents anti-patterns when diff touches agent-api)

Stay here for diagnosis, spec, placement, governance design, and greenfield bootstrap copy. ns-coder for feature diffs. Version-scoped features: ns-spec-driven.

Stop conditions

ConditionAction
No graph-spec.md and user wants code nowCreate spec or invoke architect
Greenfield assembled from snippets / another product treeStop; run scripts/bootstrap-agent-runtime.mjs
Path outside placement matrix / inventing foldersStop; propose legal path
Domain / locale / copy landing in graph/ or llm/Stop; reroute to conversation/config
Bind without parity (dispatchable but unbound)Stop; fix bind or document unbound + test
: in a new wire nameStop; use __ separators
Skill auto-inject + bind same id without explicit decisionStop; choose one mode
CrewAI requestedRedirect to appropriate skill
Change spans >3 layers without planOne-line phased plan, wait for approval
Critical security gap (secrets in state, ungoverned MCP)Block feature work; fix governance first

Related skills (ownership)

SkillOwns
ns-langgraph-agentsDoctrine, placement, inject plan, graph-spec, greenfield scaffold
ns-coderFeature diffs + review loop (not initial scaffold copy)
ns-reviewerVerdict; when diff touches agent-api, apply placement + inject + wire-name + bind-parity anti-patterns from this skill
ns-agent-adaptationConceptual adaptation design before architecture
ns-agent-architectureFramework choice before Phase 0 when unlocked
ns-spec-drivenVersion features after scaffold exists (or first task = bootstrap)
ns-investigatorRuntime debug

Forbidden

  • Emitting planner userFacingIntent as response_streaming or as Markdown in messages (SSE thinking only; composer remains sole Markdown writer)
  • Composer reply via model.invoke / single end-of-turn response_streaming dump; buffered SSE; client typewriter or delayed paint of ticks (references/streaming-and-hitl.md)
  • Writing userFacingIntent in a language other than the current user message (e.g. English progress when the operator wrote Portuguese)
  • Persisting composed system/persona prompt (base_invariant + injected) — or secrets/API keys — in graph state, checkpointer, or durable messages (rebuild system text per invoke)
  • Keying long-term user memory by thread_id, storing company/tenant facts or secrets in user memory, persisting the rendered memory block in state/checkpointer, or asking the user to confirm each memory instead of informing (references/user-memory.md)
  • Treating bootstrap / .env / configurable.locale as primary locale SoT, or persisting sticky thread locale (use conversation-observed turnLocale + Intl)
  • Passing unbounded tool/MCP output into state.messages
  • Applying tool/MCP truncate caps to skill bodies (use CONTEXT_SKILL_BODY_MAX_CHARS)
  • Trusting MCP tool metadata for security classification
  • Spawning stdio MCP subprocesses per HTTP request in production
  • memory/ compiling StateGraph
  • Domain qualify/conversation prompts in src/llm/
  • Locale/presentation under graph/
  • Nudge as fake HumanMessage
  • Tests under src/
  • Greenfield tree from snippets or another product — use templates/agent-runtime/ only

Comments

Markdown supported