@sisu-ai/mw-invariants
v12.0.0
Published
Detect protocol-level mistakes early with runtime checks for message and tool-call invariants.
Maintainers
Readme
@sisu-ai/mw-invariants
Detect protocol-level mistakes early with runtime checks for message and tool-call invariants.
Setup
npm i @sisu-ai/mw-invariantsExports
toolCallInvariant({ strict?: boolean })strict: false(default) logs a warning and continues.strict: truethrows an error to fail fast.
What It Does
- Validates the tool-calling protocol in your transcript after a step completes.
- Specifically: for each assistant message that includes
tool_calls, ensures a matchingtoolmessage exists later for every call. - Reports violations via warning logs or by throwing (strict mode).
How It Works
toolCallInvariant({ strict }) runs after await next() and inspects ctx.messages:
- Scans assistant messages with
tool_calls. - For each call, looks forward for a
toolmessage that matches bytool_call_id(preferred) orname(fallback for providers without IDs). - If any are missing, either logs a warning with details or throws when
strict: true.
This is a development-time safety net to catch mis-ordered or missing tool replies in your loop.
Example
import 'dotenv/config';
import { Agent, createConsoleLogger, InMemoryKV, NullStream, SimpleTools, type Ctx } from '@sisu-ai/core';
import { openAIAdapter } from '@sisu-ai/adapter-openai';
import { inputToMessage } from '@sisu-ai/mw-conversation-buffer';
import { registerTools } from '@sisu-ai/mw-register-tools';
import { toolCalling } from '@sisu-ai/mw-tool-calling';
import { toolCallInvariant } from '@sisu-ai/mw-invariants';
const model = openAIAdapter({ model: 'gpt-5.4' });
// Example tool
const echo = {
name: 'echo',
description: 'Echo back a message',
schema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] },
handler: async ({ text }: { text: string }) => ({ text })
};
const ctx: Ctx = {
input: 'Call the echo tool with text "hello" then answer briefly.',
messages: [{ role: 'system', content: 'Be concise.' }],
model,
tools: new SimpleTools(),
memory: new InMemoryKV(),
stream: new NullStream(),
state: {},
signal: new AbortController().signal,
log: createConsoleLogger({ level: 'info' })
};
const app = new Agent()
.use(inputToMessage)
.use(registerTools([echo as any]))
.use(toolCalling) // or iterativeToolCalling
// After tool loop completes, assert that every tool_call got a tool reply
.use(toolCallInvariant({ strict: true }));
await app.handler()(ctx);Placement & Ordering
- Place after your tool-calling middleware so it can verify the result of a turn.
- Use
strict: truein development and CI to catch regressions early; relax to warnings in production if you prefer resilience over hard failures.
When To Use
- During development/CI to ensure your tool loop respects the provider protocol.
- In staging/production as a warning-only monitor to surface unexpected provider behavior.
When Not To Use
- If your app never uses tools.
- If you handle protocol validation elsewhere (e.g., custom loop with its own assertions).
Notes & Gotchas
- Matching strategy: prefers
tool_call_id. Falls back tonamewhen the provider omits ids. - Parallel calls: works with multiple tool calls; each must have a corresponding
toolmessage. - Cross-turn behavior: invariant checks within a single turn. If you intentionally defer tool responses to a later request, adjust placement or disable strict mode.
- Streaming: this runs post-
next(). For streaming loops that push anassistant_messageevent, ensure that the final message is added toctx.messagesbefore this check or defer the check to the end of the run.
Community & Support
Discover what you can do through examples or documentation. Check it out at https://github.com/finger-gun/sisu. Example projects live under examples/ in the repo.
Documentation
Core — Package docs · Error types
Adapters — OpenAI · Anthropic · Ollama
- @sisu-ai/mw-agent-run-api
- @sisu-ai/mw-context-compressor
- @sisu-ai/mw-control-flow
- @sisu-ai/mw-conversation-buffer
- @sisu-ai/mw-cors
- @sisu-ai/mw-error-boundary
- @sisu-ai/mw-guardrails
- @sisu-ai/mw-invariants
- @sisu-ai/mw-orchestration
- @sisu-ai/mw-rag
- @sisu-ai/mw-react-parser
- @sisu-ai/mw-register-tools
- @sisu-ai/mw-tool-calling
- @sisu-ai/mw-trace-viewer
- @sisu-ai/mw-usage-tracker
- @sisu-ai/tool-aws-s3
- @sisu-ai/tool-azure-blob
- @sisu-ai/tool-extract-urls
- @sisu-ai/tool-github-projects
- @sisu-ai/tool-rag
- @sisu-ai/tool-summarize-text
- @sisu-ai/tool-terminal
- @sisu-ai/tool-web-fetch
- @sisu-ai/tool-web-search-duckduckgo
- @sisu-ai/tool-web-search-google
- @sisu-ai/tool-web-search-openai
- @sisu-ai/tool-wikipedia
Anthropic — hello · control-flow · stream · weather
Ollama — hello · stream · vision · weather · web-search
OpenAI — hello · weather · stream · vision · reasoning · react · control-flow · branch · parallel · graph · orchestration · orchestration-adaptive · guardrails · error-handling · rag-chroma · web-search · web-fetch · wikipedia · terminal · github-projects · server · aws-s3 · azure-blob
Contributing
We build Sisu in the open. Contributions welcome.
Contributing Guide · Report a Bug · Request a Feature · Code of Conduct
Star on GitHub if Sisu helps you build better agents.
Quiet, determined, relentlessly useful.
