Python 3.11–3.14
The adapter declares >=3.11,<3.15. xbbg itself also supports 3.15, but LangGraph's dependencies do not build there yet.
Python agent tools
The xbbg-langgraph adapter, imported as xbbg_langgraph, turns xbbg requests, recipes, finite live snapshots, and helpers into 35 bounded LangChain tools. Tool names match @xbbg/langgraph; Python arguments and factories use snake_case.
Not on PyPI
xbbg-langgraph has not been published to PyPI, so pip install xbbg-langgraph does not work. Install it from a checkout of the xbbg repository, as shown below.
git clone --depth 1 --branch v1.8.0 https://github.com/underloam/xbbg.git
pip install ./xbbg/py-xbbg-langgraph
# For the create_agent example below:
pip install langchain langchain-openai
# For custom graphs without the LangChain agent package:
pip install "langgraph>=1.2,<2"The adapter declares >=3.11,<3.15. xbbg itself also supports 3.15, but LangGraph's dependencies do not build there yet.
xbbg>=1.6.0,<2, langchain-core>=1.4.0,<2, and pydantic>=2.10,<3; on Python 3.14 also langsmith<0.9. Graph workflows target LangGraph 1.2 or newer.
Live calls need authorized Bloomberg connectivity and the SDK runtime, as for any xbbg request. Creating tools and reading their schemas does not import the native extension or start a session.
The v1.8.0 checkout builds xbbg-langgraph 0.1.0. Ordinary pip install xbbg installs no LangChain packages. See Installation for the Bloomberg runtime.
With xbbg 1.8.0 the adapter checks the size of each native cell and metadata value before copying it into a result. Older xbbg releases, which the xbbg>=1.6.0 floor still allows, copy them first and apply the limits afterwards.
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
from xbbg_langgraph import BLOOMBERG_TOOL_INSTRUCTIONS, create_all_bloomberg_tools
tools = create_all_bloomberg_tools(
max_securities=10,
max_fields=25,
max_rows=500, # application artifact
max_content_rows=50, # model-facing preview
disabled_tools={"xbbg_bql", "xbbg_bsrch"},
)
# Configure OPENAI_API_KEY and Bloomberg access before invoking.
agent = create_agent(
model=ChatOpenAI(model="gpt-4.1"),
tools=tools,
system_prompt=BLOOMBERG_TOOL_INSTRUCTIONS,
)
result = agent.invoke({
"messages": [{"role": "user", "content": "Get PX_LAST for IBM US Equity."}],
})Bind the tools to your model and route tool calls through ToolNode:
from langchain_core.messages import SystemMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import START, MessagesState, StateGraph
from langgraph.prebuilt import ToolNode, tools_condition
from xbbg_langgraph import BLOOMBERG_TOOL_INSTRUCTIONS, create_bloomberg_tools
tools = create_bloomberg_tools(max_securities=5, max_fields=5)
model = ChatOpenAI(model="gpt-4.1").bind_tools(tools)
def call_model(state: MessagesState) -> dict:
response = model.invoke([SystemMessage(BLOOMBERG_TOOL_INSTRUCTIONS), *state["messages"]])
return {"messages": [response]}
builder = StateGraph(MessagesState)
builder.add_node("model", call_model)
builder.add_node("tools", ToolNode(tools))
builder.add_edge(START, "model")
builder.add_conditional_edges("model", tools_condition)
builder.add_edge("tools", "model")
graph = builder.compile()ToolNode produces ToolMessages whose content goes back to the model and whose artifact holds the application envelope described under Results.
| Factory | Returns |
|---|---|
create_all_bloomberg_tools() | All 35 tools (BLOOMBERG_TOOL_NAMES) |
create_bloomberg_tools() | The 24 request, recipe, auction, and snapshot tools (BLOOMBERG_CORE_TOOL_NAMES) |
create_bloomberg_ext_tools() | The 11 helper tools (BLOOMBERG_EXT_TOOL_NAMES) |
create_<name>_tool() | One tool, named after the tool without its xbbg_ prefix: create_bdp_tool() builds xbbg_bdp, create_ext_chart_spec_tool() builds xbbg_ext_chart_spec |
BloombergToolsOptions instance, not both; mixing them raises TypeError.disabled_tools removes tools from the three group factories. An unknown name fails validation, and calling an individual factory for a tool you disabled raises ValueError.StructuredTool with response_format="content_and_artifact" and supports .invoke() and .ainvoke().from xbbg_langgraph import BloombergToolsOptions, create_all_bloomberg_tools, create_bdp_tool
options = BloombergToolsOptions(max_rows=200, max_content_rows=20, request_timeout=30.0)
tools = create_all_bloomberg_tools(options)
bdp_only = create_bdp_tool(max_securities=3)BLOOMBERG_TOOL_INSTRUCTIONS is system-prompt text for the model. It tells the model to ask before choosing an ambiguous security, field, date range, or universe; never to invent tickers, fields, overrides, or BQL functions; to pass identifiers exactly as supplied (/isin/<ISIN>, /cusip/<CUSIP>); to look up uncertain fields with xbbg_bflds; to issue one request per dataset; and to report empty, truncated, or errored results instead of filling gaps.
get_bloomberg_tool_instructions(include_extension_guidance=True, include_limit_reminder=True) builds the same text with optional sections. Drop the helper guidance when the model does not get the helper tools:
from xbbg_langgraph import create_bloomberg_tools, get_bloomberg_tool_instructions
tools = create_bloomberg_tools()
prompt = get_bloomberg_tool_instructions(include_extension_guidance=False)BloombergToolsOptions is a frozen Pydantic model. Unknown keys are rejected, and integer limits are strict: booleans and floats are not accepted.
| Option | Default | Constraint | Bounds |
|---|---|---|---|
engine | None | An xbbg.blp.Engine | Engine for every call; see Engines |
max_securities | 25 | > 0 | Securities per call, ISIN lists, and pcs_overrides entries |
max_fields | 25 | > 0 | Fields per call and entries per kwargs or override map; CDX bundles must fit |
max_rows | 500 | > 0 | Rows retained in the artifact; chart-spec input rows |
max_string_chars | 2,000 | > 0 | Characters per input string and per result string |
max_result_bytes | 1,048,576 | ≥ 256 | Serialized artifact, including its envelope |
max_result_nodes | 50,000 | ≥ 10 | Values and properties inspected while bounding one result |
max_content_bytes | 65,536 | ≥ 256 | Serialized model-facing content, including its envelope |
max_content_rows | 50 | > 0 | Rows retained in model-facing content |
max_bql_query_chars | 4,000 | > 0 | xbbg_bql queries and generated recipe queries |
max_search_spec_chars | 1,000 | > 0 | search_spec for xbbg_bsrch and xbbg_bflds |
max_stream_updates | 10 | > 0 | Largest max_updates a snapshot accepts |
max_stream_wait_ms | 15,000 | > 0 | Largest and default snapshot timeout_ms |
request_timeout | 60.0 | > 0, finite | Seconds allowed for each tool call |
validate_fields | None | bool | Default field validation for xbbg_bdp, xbbg_bdh, xbbg_bds, and the CDX bundles; a per-call value wins |
disabled_tools | empty | Known tool names | Tools left out by the group factories |
The limits are also written into each tool's JSON schema, so the model sees them.
Each call produces two independently bounded projections of the same result: model-facing content (max_content_rows, max_content_bytes) and an application artifact (max_rows, max_result_bytes). A smaller preview never shrinks the artifact. Invoke with a full tool call, as agents and ToolNode do, to receive a ToolMessage carrying both; bare arguments return only the content string, following LangChain's normal contract.
from xbbg_langgraph import create_bdp_tool
tool = create_bdp_tool(max_securities=1, max_fields=1)
message = tool.invoke({
"type": "tool_call",
"id": "reference-price",
"name": "xbbg_bdp",
"args": {"securities": ["IBM US Equity"], "fields": ["PX_LAST"]},
})
print(message.content) # JSON envelope for the model
print(message.artifact) # JSON-safe envelope for your applicationBoth projections use the same envelope keys as the JavaScript adapter:
| Key | Meaning |
|---|---|
tool | Tool name |
data | The bounded result |
rowCount | Source row count, or None when unknown; not the number of rows kept |
truncated | True when anything was omitted or shortened |
truncation | Optional {"reasons": [...]} from max_rows, max_string_chars, max_result_bytes, max_result_nodes, max_result_depth, circular_reference, binary_data, unsupported_value, upstream_truncation |
hasErrors | Present and True when Bloomberg errors were detected, even if their details were clipped |
data is a list of row objects or, when the Arrow table carries metadata, an object with rows, the raw metadata, and any parsed diagnostics: securityErrors, fieldErrors, fieldExceptions, eidData, and delayed (from the metadata keys xbbg.security_errors, xbbg.field_errors, xbbg.field_exceptions, xbbg.eid_data, and xbbg.delayed). fieldErrors holds the field ids Bloomberg refused, which xbbg 1.8.0 reports for xbbg_bflds even when no field was answered.xbbg.field_exceptions as a compact dictionary. The adapter expands only the diagnostics it keeps and omits unreadable ones with the unsupported_value reason instead of failing the result.null with the unsupported_value reason. Binary values, including sparse-update presence bitmaps, become {"encoding": "base64", "data": ..., "byteLength": ..., "truncated": ...} so null and absent stay distinguishable. Nesting is capped at depth 32.Live data is exposed only as finite snapshots that always unsubscribe:
| Tool | Service | Inputs |
|---|---|---|
xbbg_stream_snapshot | //blp/mktdata | tickers, fields, max_updates |
xbbg_mktbar_snapshot | //blp/mktbar | One ticker, max_updates; fields may only be ["LAST_PRICE"], and bar_size=1 is added unless options sets bar_size |
xbbg_depth_snapshot | //blp/mktdepthdata | One ticker, max_updates; requests all available scalar fields unless you pass fields, and all_fields=False requires a nonempty list. Needs B-PIPE with depth entitlements |
max_updates is required and at most max_stream_updates. timeout_ms defaults to max_stream_wait_ms (15 seconds) and cannot exceed it.drain, all_fields, conflate (//blp/mktdata only), flush_threshold, stream_capacity, overflow_policy, and Bloomberg subscription options.overflow_policy accepts drop_newest or block. When omitted, snapshots use drop_newest regardless of the engine's default, because snapshot rows cannot describe gaps; lossy delivery modes are not offered.flush_threshold defaults to 1, so each update is one native read even though xbbg 1.8.0 engines batch up to 16 queued updates by default.updateCount, maxUpdates, timeoutMs, reason (max_updates, timeout, or done), and updates. If collection succeeded but releasing the subscription failed, the updates are kept and unsubscribeError reports the failure.See Streaming for open-ended subscriptions in application code.
Without engine, tools use xbbg's global engine (set up with xbbg.configure()) or the engine scoped in the caller's context. Pass engine= to route every call through an application-owned xbbg.blp.Engine; each call enters it as a context manager. The adapter never configures, resets, or shuts down an engine.
With xbbg 1.8.0, the engine's key_column names the column that holds each row's security. The default, ticker, is deprecated and its results emit a FutureWarning; set key_column="security" with xbbg.configure() or blp.Engine() to switch.
from xbbg import blp
from xbbg_langgraph import create_all_bloomberg_tools
engine = blp.Engine(host="localhost", port=8194, request_timeout_ms=30_000)
tools = create_all_bloomberg_tools(engine=engine, request_timeout=45.0)
# ... run the agent ...
engine.shutdown() # the application owns the engine's lifecyclerequest_timeout is a coroutine deadline in seconds around each tool's Bloomberg work (default 60); bounding the result afterwards is not counted against it. It cannot preempt synchronous SDK startup or subscription cleanup. Set the engine's request_timeout_ms (default 0, no timeout) to bound requests inside the engine, and its connection settings for startup..invoke() runs the call on its own event loop and raises RuntimeError inside a running loop; use await tool.ainvoke(...) (and graph.ainvoke) in async code..ainvoke() cancels the tool's coroutine. Snapshot tools still release their subscription, without draining, before the cancellation propagates.See Configuration for engine settings.
return_eids=True is accepted by xbbg_bdp, xbbg_bdh, xbbg_bds, xbbg_bdib, and xbbg_bdtick; the IDs appear as eidData in data. Pass them to xbbg_check_entitlements (eids, up to 10,000 positive IDs; service, default //blp/refdata), which returns {"entitled": ..., "failedEids": [...]}. Do not treat a truncated EID map as complete.xbbg_delay_status returns one row per unique security with delayed, delay_minutes, exchange_delay, exch_code, realtime_eid1 to realtime_eid4, delayed_eid, and error. check_identity=True adds realtime_entitled and delayed_entitled and needs an EMRS-enrolled Desktop API user or SAPI/B-PIPE authorization.on_delayed ("warn", "raise", or "ignore") on xbbg_bdp, xbbg_bdh, xbbg_bdib, and xbbg_bdtick checks delay alongside the request. raise fails the call when Bloomberg delivers delayed data; warn and ignore add a per-security delayed map to data, and warn also emits xbbg's BlpDelayedDataWarning in your process. History and intraday tools check only windows that reach the last 24 hours.See Entitlements for the underlying xbbg calls.
xbbg_resolve_venues and xbbg_auction_snapshot take securities (tickers, bare ISINs, /isin/ or /bbgid/ topics, with explicit venue suffixes kept) and optional pcs_overrides mapping preferred-stock exchange names to pricing-source codes. They keep one row per input with status and error; failed venues keep their row with null data fields. xbbg_auction_snapshot takes optional fields; omitted or empty selects AUCTION.DEFAULT. Time-of-day values are terminal-local, and a snapshot does not report delay, so pair it with xbbg_delay_status. See Exchange Auctions.
xbbg_ext_chart_spec turns rows you already have, typically from an earlier data tool, into an inline Vega-Lite v5 specification. It neither fetches Bloomberg data nor renders anything.
from xbbg_langgraph import create_ext_chart_spec_tool
chart = create_ext_chart_spec_tool()
message = chart.invoke({
"type": "tool_call",
"id": "chart-1",
"name": "xbbg_ext_chart_spec",
"args": {
"source": "bdh",
"rows": [
{"ticker": "AAPL US Equity", "date": "2024-01-02", "value": 190.1},
{"ticker": "AAPL US Equity", "date": "2024-01-03", "value": 188.4},
],
"x_field": "date",
"y_fields": ["value"],
"series_field": "ticker",
"title": "AAPL PX_LAST",
},
})
chart_data = message.artifact["data"]source (bdh, bdib, holdings, depth, or rows), rows (at most max_rows), and optional chart (line, area, bar, scatter, candlestick, or depth; the default follows source), title, max_points, x_field, y_fields, series_field, label_field, value_field, open_field, high_field, low_field, close_field, side_field, price_field, and size_field. Every named field must exist in the rows.kind ("xbbg.visualization"), version, component ("xbbg_chart"), renderer ("vega-lite"), rowCount, inputRowCount, truncatedInput, source, chart, summary, spec, and warnings.data["spec"] is present and data.get("renderable") is not False. Truncation by max_points keeps a valid spec and adds a warning; clipping by the result budgets sets spec to None and renderable to False.<TICKER> <EXCHANGE> Equity for preferreds, corporate bonds, and ETF holdings, and <TICKER> Index for index members. The builders never guess a suffix. Recipe fields accept identifiers and argument-free BQL field access only; use xbbg_bql for expressions.xbbg_bql accepts only query, and xbbg_bflds only fields or search_spec; other keyword options are rejected rather than ignored. Configure bql_app_name on the engine to set the BQL application context.xbbg_corporate_bonds has no active_only input. Omitting ccy means all currencies, unlike the Python recipe's USD default.recovery_rate on xbbg_ext_cdx is a percentage from 0 to 100: 40 means 40%, not 0.40. On xbbg_yas, yield_val is in percentage points and spread in basis points.kwargs and overrides carry Bloomberg request values only. Infrastructure and typed call options such as engine, backend, format, host, or port are rejected in either snake_case or camelCase. Per-security override maps must be keyed by a security in securities.YYYY-MM-DD or YYYYMMDD strings, integer YYYYMMDD values, or epoch milliseconds. Datetimes must be ISO 8601 with a time component (optional Z or offset) or epoch milliseconds. start must not be after end, and both must be either naive or offset-aware.Compared with @xbbg/langgraph, Python bounds each call with request_timeout in seconds, where JavaScript sets engineConfig.requestTimeoutMs on lazily created engines only. Python content is the JSON envelope alone, without the JavaScript summary line, and its truncation carries only reasons.
Required inputs are listed first.
| Tool | Purpose | Inputs |
|---|---|---|
xbbg_bdp | Reference data | securities, fields; overrides, kwargs, format, include_security_errors, validate_fields, return_eids, on_delayed |
xbbg_bdh | Historical series | securities, fields, start, end; format (adds semi_long), overrides, kwargs, validate_fields, return_eids, on_delayed |
xbbg_bds | One bulk or table field | securities, field; overrides, kwargs, validate_fields, return_eids |
xbbg_bdib | Intraday bars | ticker, start, end, interval; event_type, request_tz, output_tz, kwargs, return_eids, on_delayed |
xbbg_bdtick | Intraday ticks | ticker, start, end; event_types, seven include_* flags, request_tz, output_tz, kwargs, return_eids, on_delayed |
xbbg_check_entitlements | Check entitlement IDs | eids; service |
xbbg_delay_status | Delayed or real-time status per security | securities; check_identity |
xbbg_bql | One complete BQL expression | query |
xbbg_bsrch | Saved search or grid | search_spec; kwargs, overrides |
xbbg_bqr | Fixed-income dealer quotes | ticker, start, end; event_types (default BID and ASK), include_broker_codes |
xbbg_bflds | Field metadata and search; with xbbg 1.8.0, results end with the field id column | Exactly one of fields or search_spec |
xbbg_beqs | Named Bloomberg equity screen | screen; asof, group, screen_type, kwargs, overrides |
xbbg_yas | YAS yield and spread analytics | tickers, fields; settle_dt, yield_type (1–9), yield_val, price, spread, benchmark |
xbbg_preferreds | Preferreds of an issuer | equity_ticker; fields |
xbbg_corporate_bonds | Corporate debt universe of a company | ticker; ccy, fields |
xbbg_index_members | Index constituents | index; asof, field (INDX_MWEIGHT, INDX_MEMBERS, INDX_MEMBERS3) |
xbbg_resolve_isins | Resolve raw ISINs | isins |
xbbg_issuer_isins | Bond ISINs to issuer equity ISINs | bond_isins |
xbbg_resolve_venues | Validated auction venues | securities; pcs_overrides |
xbbg_auction_snapshot | Auction and imbalance fields on primary venues | securities; fields, pcs_overrides |
xbbg_etf_holdings | ETF holdings | etf_ticker; fields |
xbbg_stream_snapshot | Finite //blp/mktdata snapshot | tickers, fields, max_updates; snapshot controls |
xbbg_mktbar_snapshot | Finite //blp/mktbar snapshot | ticker, max_updates; fields, snapshot controls |
xbbg_depth_snapshot | Finite //blp/mktdepthdata snapshot | ticker, max_updates; fields, snapshot controls |
xbbg_ext_ticker | Ticker hygiene | operation: parse_ticker (generic futures-style tickers only), normalize_tickers, filter_equity_tickers, is_specific_contract, validate_generic_ticker |
xbbg_ext_futures | Futures contract construction and selection | operation: build_futures_ticker, generate_candidates, contract_index, filter_candidates_by_cycle, filter_valid_contracts, get_futures_months |
xbbg_ext_cdx | CDX parsing, series, and data bundles | operation: parse_cdx_ticker, previous_cdx_series, cdx_gen_to_specific, cdx_info, cdx_pricing, cdx_risk (recovery_rate 0–100) |
xbbg_ext_currency | Currency planning, not FX quotes | operation: build_fx_pair, same_currency, currencies_needing_conversion |
xbbg_ext_bql_builder | Build, but do not run, recipe BQL | operation: build_preferreds_query, build_corporate_bonds_query, build_etf_holdings_query |
xbbg_ext_chart_spec | Vega-Lite spec from rows | source, rows; chart options |
xbbg_ext_market_session | Read-only session and timezone helpers | operation: derive_sessions, get_market_rule, infer_timezone, session_times_to_utc, default_turnover_dates, default_bqr_datetimes, get_exchange_override, list_exchange_overrides |
xbbg_ext_yas_overrides | YAS override pairs without a request | settle_dt, yield_type, spread, yield_val, price, benchmark (all optional) |
xbbg_ext_constants | Constant lookups | operation: parse_date, fmt_date, get_month_code, get_month_name, get_futures_months, get_dvd_type, get_dvd_types, get_dvd_cols, get_etf_cols |
xbbg_ext_columns | Column rename mappings | operation: rename_dividend_columns, rename_etf_columns, build_earning_header_rename |
xbbg_ext_calculate | Level percentages for earnings hierarchies | operation: calculate_level_percentages; values, levels (1, 2, or null; same length) |
The helper tools run locally on xbbg's native helpers and never contact Bloomberg, except the cdx_info, cdx_pricing, and cdx_risk data bundles.
The same 35 tools for LangChain.js and LangGraph.js.
Give Claude Code, OpenCode, or Claude Desktop Bloomberg tools without writing an agent.
Entitlement IDs, identity checks, and delayed-data status.
Venue routing and auction snapshots behind the auction tools.