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

@xbbg/langgraph

v1.3.0

Published

LangChain and LangGraph tools for Bloomberg workflows backed by @xbbg/core

Readme

@xbbg/langgraph

LangChain/LangGraph-compatible Bloomberg tools backed by @xbbg/core.

This package is a reusable tool adapter. It is not a chat app, HTTP server, MCP server, browser package, or agent framework.

Prerequisites

Bloomberg connectivity is still provided by @xbbg/core: an installed Bloomberg Terminal/Desktop API, B-PIPE, SAPI, or ZFP setup plus Bloomberg SDK runtime libraries must be available on the server running the tools.

Install

Tool package only:

npm install @xbbg/langgraph @xbbg/core @langchain/core

LangGraph app:

npm install @xbbg/langgraph @xbbg/core @langchain/core @langchain/langgraph @langchain/openai

Current LangChain agent app:

npm install @xbbg/langgraph @xbbg/core @langchain/core langchain @langchain/openai

Agent guidance

Append the exported instructions to your system prompt:

import { BLOOMBERG_TOOL_INSTRUCTIONS } from "@xbbg/langgraph";

The instructions tell the model to ask clarifying questions for ambiguous tickers, fields, date ranges, currencies, periodicity, overrides, or universes; request /isin/{isin} for ISIN identifiers and /cusip/{cusip} for CUSIPs; use xbbg_bflds for unknown fields; prefer finite recipe tools for BEQS/YAS/universe workflows; use bounded snapshot tools instead of open subscriptions; keep requests bounded; and report empty, truncated, or errored responses directly.

LangChain createAgent example

import { createAgent } from "langchain";
import { ChatOpenAI } from "@langchain/openai";
import { createAllBloombergTools, BLOOMBERG_TOOL_INSTRUCTIONS } from "@xbbg/langgraph";

const tools = createAllBloombergTools({
  maxSecurities: 10,
  maxFields: 10,
});

const agent = createAgent({
  model: new ChatOpenAI({ model: "gpt-4.1" }),
  tools,
  systemPrompt: BLOOMBERG_TOOL_INSTRUCTIONS,
});

const result = await agent.invoke({
  messages: [{ role: "user", content: "Get <FIELD> for <TICKER> <MARKET_SECTOR>." }],
});

LangGraph example

createReactAgent from @langchain/langgraph/prebuilt is deprecated upstream in favor of createAgent from langchain, but it is still common in LangGraph examples and accepts these tools because they are normal LangChain tools.

import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { ChatOpenAI } from "@langchain/openai";
import { createBloombergTools, BLOOMBERG_TOOL_INSTRUCTIONS } from "@xbbg/langgraph";

const agent = createReactAgent({
  llm: new ChatOpenAI({ model: "gpt-4.1" }),
  tools: createBloombergTools({ maxSecurities: 5, maxFields: 5 }),
  prompt: BLOOMBERG_TOOL_INSTRUCTIONS,
});

For custom graphs, bind the tools to your model and route tool calls through LangGraph's ToolNode:

import { AIMessage } from "@langchain/core/messages";
import { END, MessagesAnnotation, START, StateGraph } from "@langchain/langgraph";
import { ToolNode } from "@langchain/langgraph/prebuilt";
import { ChatOpenAI } from "@langchain/openai";
import { createBloombergTools, BLOOMBERG_TOOL_INSTRUCTIONS } from "@xbbg/langgraph";

const tools = createBloombergTools({ maxSecurities: 5, maxFields: 5 });
const model = new ChatOpenAI({ model: "gpt-4.1" }).bindTools(tools);
const toolNode = new ToolNode(tools);

const callModel = async (state: typeof MessagesAnnotation.State) => ({
  messages: [
    await model.invoke([
      { role: "system", content: BLOOMBERG_TOOL_INSTRUCTIONS },
      ...state.messages,
    ]),
  ],
});

const route = (state: typeof MessagesAnnotation.State) => {
  const last = state.messages.at(-1);
  return last instanceof AIMessage && last.tool_calls?.length ? "tools" : END;
};

const graph = new StateGraph(MessagesAnnotation)
  .addNode("model", callModel)
  .addNode("tools", toolNode)
  .addEdge(START, "model")
  .addConditionalEdges("model", route)
  .addEdge("tools", "model")
  .compile();

All tools use LangChain responseFormat: "content_and_artifact". In ToolNode, the tool message content starts with a compact summary and then includes bounded model-readable JSON; artifact contains the structured bounded envelope for application code.

Tool factories

Core Bloomberg request tools:

  • xbbg_bdp - reference/current fields for a bounded securities list and explicit fields list.
  • xbbg_bdh - historical time series; requires explicit start and end.
  • xbbg_bds - one Bloomberg bulk/table field.
  • xbbg_bdib - intraday bars; requires explicit start, end, and interval.
  • xbbg_bdtick - intraday ticks; requires explicit start, end, and event types when the default stream is not intended.
  • xbbg_bql - BQL expressions only.
  • xbbg_bsrch - Bloomberg search/grid requests, not normal security lookup.
  • xbbg_bqr - Bloomberg Quote Request / fixed-income dealer quotes; prefer identifiers such as /isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>.
  • xbbg_bflds - field metadata/search; use first for uncertain mnemonics.
  • xbbg_beqs - named Bloomberg BEQS equity screens.
  • xbbg_yas - fixed-income YAS recipe fields for yield, duration, spread, benchmark, or price analytics.
  • xbbg_preferreds - preferred stock discovery for one equity ticker.
  • xbbg_corporate_bonds - corporate bond universe query for one issuer/company ticker.
  • xbbg_index_members - index constituents through the core index recipe.
  • xbbg_resolve_isins - raw ISIN-to-security resolution; pass raw ISIN strings to this recipe only.
  • xbbg_issuer_isins - issuer/bond ISIN workflow starting from known bond ISIN strings.
  • xbbg_etf_holdings - ETF holdings for one ETF ticker.
  • xbbg_stream_snapshot - bounded //blp/mktdata live observation that always unsubscribes.
  • xbbg_mktbar_snapshot - bounded //blp/mktbar live bar observation for one ticker.
  • xbbg_depth_snapshot - bounded //blp/mktdepthdata market-depth observation for one ticker.

Securities are passed through in the form the user supplied them: Bloomberg tickers as <TICKER> <MARKET_SECTOR> (for example <TICKER> <EXCHANGE> Equity, <INDEX_TICKER> Index, <CCY_PAIR> Curncy), raw ISINs as /isin/<ISIN>, raw CUSIPs as /cusip/<CUSIP>. The market sector ending is Bloomberg's yellow key — Equity, Index, Curncy, Comdty, Corp, Govt, Muni, Mtge, M-Mkt, or Pfd (preferred securities) — and request tools pass it through to Bloomberg unvalidated. The agent guidance and every securities/ticker field description instruct the model that the ticker format is a template, not authorization to construct one — identifiers are never converted into guessed tickers; xbbg_resolve_isins exists for explicit resolution. Note xbbg_ext_ticker's parse_ticker is narrower than the request tools: it parses generic futures-style tickers only (Index/Curncy/Comdty/Corp, or <ROOT><N> <EXCHANGE> Equity) and rejects other sectors. BQL is passed as one complete expression string. Use placeholder shapes such as get(<FIELD>) for('<TICKER> <MARKET_SECTOR>'), get(<FIELD_1>, <FIELD_2>) for(['<TICKER_1> <MARKET_SECTOR>', '<TICKER_2> <MARKET_SECTOR>']), get(<FIELD>, <WEIGHT_FIELD>) for(holdings('<ETF_TICKER> <MARKET_SECTOR>')), or get(<FIELD>) for(members('<INDEX_TICKER> <MARKET_SECTOR>')) with(...). Prefer xbbg_bdp/xbbg_bdh for simple reference or historical requests.

Dealer quote / BQR workflows in xbbg use fixed-income identifiers with a quote source, for example /isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>; use xbbg_bqr for that workflow and xbbg_bdtick for raw intraday ticks.

Streaming surfaces are intentionally exposed only as bounded snapshot tools. Each snapshot requires maxUpdates, applies the configured maxStreamUpdates/maxStreamWaitMs caps, stops on count, timeout, or stream completion, and calls unsubscribe(false) unless drain: true is explicitly provided. The package does not expose open-ended async subscription iterators as agent tools. If collection succeeds but releasing the subscription fails, the snapshot result still returns the collected updates and reports the failure in an unsubscribeError field instead of discarding data.

import { createBloombergTools, createBdpTool } from "@xbbg/langgraph";

const tools = createBloombergTools();
const bdpOnly = createBdpTool({ maxSecurities: 3 });

Extension helper tools:

  • xbbg_ext_ticker - ticker hygiene before live requests: parse, normalize lists, filter equity tickers, check specific contracts, and validate generic futures tickers.
  • xbbg_ext_futures - futures construction and selection: month-code lookup, build a specific contract, generate candidates from a generic, rank contracts, filter by cycle, and filter valid contracts for a date.
  • xbbg_ext_cdx - CDX workflows: parse CDX tickers, roll to previous series, resolve generic to specific series, and run predefined CDX info/pricing/risk field bundles.
  • xbbg_ext_currency - currency planning: build FX pair metadata, test same-currency requests, and identify currencies needing conversion to a target.
  • xbbg_ext_bql_builder - BQL query builders for preferred stocks, corporate bonds, and ETF holdings; prefer these over hand-writing those query shapes.
  • xbbg_ext_market_session - exchange sessions and timezones: derive sessions, infer timezone, convert local session times to UTC, fetch market rules, compute turnover/BQR default ranges, and inspect exchange overrides.
  • xbbg_ext_yas_overrides - build flat YAS override maps for lower-level fixed-income BDP workflows. Prefer xbbg_yas when you want the actual YAS recipe result.
  • xbbg_ext_constants - static constants and formatting helpers for dates, futures months, dividend types, and ETF/dividend columns.
  • xbbg_ext_columns - rename helpers for dividend, ETF, and earnings-shaped Bloomberg responses.
  • xbbg_ext_calculate - small numeric helper for level percentage calculations.
import { createBloombergExtTools, createAllBloombergTools } from "@xbbg/langgraph";

const helperTools = createBloombergExtTools();
const allTools = createAllBloombergTools({
  disabledTools: ["xbbg_bql", "xbbg_bsrch"],
});

Engine handling

By default the first tool invocation lazily imports @xbbg/core, calls connect(engineConfig), and reuses the resulting engine across the tool set. Parallel LangGraph tool calls share the same in-flight initialization promise.

Lazily connected engines get a hard per-request timeout (DEFAULT_ENGINE_REQUEST_TIMEOUT_MS, 60s) because @xbbg/core disables request timeouts by default, which would let a wedged Terminal session hang tool calls forever. Pass engineConfig: { requestTimeoutMs: ... } to change it, or 0 to disable. A user-supplied engine is used as-is — its configuration and lifecycle (including disconnect) stay with the caller.

import * as xbbg from "@xbbg/core";
import { createBloombergTools } from "@xbbg/langgraph";

const engine = await xbbg.connect({ host: "localhost", port: 8194 });
const tools = createBloombergTools({ engine });

Cancellation

Tools honor the LangChain/LangGraph AbortSignal (graph.invoke(input, { signal })): an aborted call rejects immediately, already-cancelled calls never start Bloomberg work, and snapshot tools stop collecting and unsubscribe right away (skipping drain) instead of running out their timeout. In-flight Bloomberg request/response calls cannot be cancelled mid-flight; they are bounded by the engine request timeout above.

Limits and outputs

Defaults:

  • maxSecurities = 25
  • maxFields = 25
  • maxRows = 500
  • maxStringChars = 2000
  • maxStreamUpdates = 10
  • maxStreamWaitMs = 15000

Date inputs accept YYYY-MM-DD or YYYYMMDD strings, integer YYYYMMDD values (parsed as calendar dates), and epoch milliseconds; ambiguous numbers between those ranges and ambiguous MM/DD/YYYY strings are rejected with actionable schema errors. Date instances are deliberately not part of the wire contract: JSON tool calls cannot carry them and z.date() breaks JSON Schema conversion in zod v4.

Schemas only advertise parameters the engine accepts: format exists on xbbg_bdp/xbbg_bdh only, because the engine rejects it for BulkData (xbbg_bds), BQL, search, field-info, and BEQS output; a model-sent format on those tools is stripped rather than forwarded. The exported toolParameterJsonSchema(tool) returns the provider-ready $ref-free JSON Schema used in each tool's embedded provider definition.

Empty results are called out in the model-facing summary (empty result; verify identifiers, fields, and date range before concluding no data exists) so agents distinguish "no rows" from silent failure instead of inventing data.

Each tool uses backend: "json" for finite request results and LangChain content_and_artifact output. The model-facing content starts with a short summary and then includes bounded JSON data:

xbbg_bdp: 1 row; truncated=false
{"tool":"xbbg_bdp","rowCount":1,"truncated":false,"data":[{"security":"<TICKER> <MARKET_SECTOR>","field":"<FIELD>","value":"<VALUE>"}]}

The artifact is the same bounded structured envelope for application code:

{
  "tool": "xbbg_bdp",
  "rowCount": 1,
  "truncated": false,
  "data": [{ "security": "<TICKER> <MARKET_SECTOR>", "field": "<FIELD>", "value": "<VALUE>" }]
}

When invoking tools outside an agent graph and you need the artifact, invoke with a tool-call id (or use LangGraph ToolNode) so LangChain returns a ToolMessage with artifact.

Use smaller factories or disabledTools when broad BQL/search helpers are not appropriate for a deployment.