npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@orangecheck/agent-langgraph

v0.2.0

Published

Wrap LangGraph tool nodes with OC Agent scope enforcement and emit a signed agent-action envelope per execution. Binds the action to the graph-state hash so verifiers replay the audit against the persisted graph snapshot.

Downloads

364

Readme

@orangecheck/agent-langgraph

Wrap LangGraph tool-node executions in OC Agent action envelopes. Binds each action to the graph-state hash at execution time — so verifiers replaying the audit against a persisted graph snapshot can confirm the action fired against the expected state, not a divergent fork.

Why

LangGraph composes long-running stateful agents from typed nodes. The compliance question is harder than for stateless adapters: at what graph state did this agent take this action? Without a state-bound action receipt, "the model called this tool" loses its temporal grounding the moment the graph forks, retries, or replays.

This adapter canonicalizes (verb, args, callId, graph_state_hash) — one extra field over the stateless adapters in this family — so the action envelope binds the agent's signature to the exact state snapshot at execution time. Two verifiers re-deriving the action from a persisted graph snapshot get the same envelope id only when the snapshot's state-hash matches.

Status

v0.0.1 · in design. API shape is stable; the canonicalization layout ({args, call_id, graph_state_hash, verb} lexicographic, RFC 8785 canonical JSON, trailing LF) is locked. Production wiring with specific LangGraph release lines is intentionally not baked in — ocToolNode() is provider/version-agnostic so you can call it from any release of @langchain/langgraph you're already on.

Install

npm i @orangecheck/agent-langgraph
# peer deps:
npm i @orangecheck/agent-core @orangecheck/agent-signer

Quickstart

import { StateGraph } from '@langchain/langgraph';
import { ocToolNode } from '@orangecheck/agent-langgraph';

const createInvoice = ocToolNode({
    verb:    'invoice.create',
    execute: async (args) => myInvoiceCreateImpl(args),
});

const graph = new StateGraph(MyState).addNode('createInvoice', async (state) => {
    const args   = pickToolArgs(state);
    const callId = state.lastToolCallId;

    const { result, action } = await createInvoice.execute(args, {
        agent, delegation, callId, graphState: state,
    });

    await yourAuditPipeline.append(action);
    return mergeResultIntoState(state, result);
});

The pattern: ocToolNode defines the OC-Agent-shaped wrapper; your LangGraph node glue passes the live graphState so the wrapper hashes it inline.

What gets stamped

Stamp's content.hash is a SHA-256 of:

{
  "args":             <canonical JSON of args>,
  "call_id":          "<sdk-assigned tool call id>",
  "graph_state_hash": "sha256:<64-hex>",
  "verb":             "<verb>"
}

The graph_state_hash is itself a sha256:<64-hex> over the canonicalized graph state object. Two replays against the same persisted state produce the same hash; a divergent state (extra messages, mutated step counter, anything) produces a different hash and the action envelope will not match.

Default scope_exercised is langgraph:tool(verb=<verb>). Override via scopeExercised.

API

  • graphStateHash(state) — stable sha256:<64-hex> of a LangGraph state object.
  • canonicalizeToolCall(call) — RFC 8785 canonical bytes.
  • toolCallHash(call)sha256:<64-hex> for content.hash.
  • stampToolCall(input) — sign without executing.
  • ocToolNode({verb, execute}) — wrapped tool node with state-aware canonicalization.

Replay verification

To verify an action against a persisted graph snapshot:

  1. Decode the action envelope's content hash.
  2. Recompute graphStateHash(persisted_state) and check it equals the graph_state_hash declared in the canonicalized content.
  3. Run the standard verifyAction() from @orangecheck/agent-core against the action + delegation + Bitcoin headers.

The replay verifier picks up forks automatically: if the persisted snapshot doesn't match the state at execution time, the graph_state_hash differs and the action's content hash won't reproduce.

License

MIT.

Related