From 99bc3a4951c6496671ec306f76129be8f40f191c Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 14 Oct 2026 22:10:08 +0000 Subject: [PATCH 1/3] docs(examples): show startup content capture with configure Add a standalone example that calls configure once before the first AI invocation. Handlers are built without a capture_content argument. --- examples/capture_content.py | 61 +++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 examples/capture_content.py diff --git a/examples/capture_content.py b/examples/capture_content.py new file mode 100644 index 00000000..495332fd --- /dev/null +++ b/examples/capture_content.py @@ -0,0 +1,61 @@ +""" +Example: enable conversation content for every handler at process startup. + +The handlers in the global registry are built with no ``capture_content`` +argument. They read the process default when they run. ``configure`` is +separate from ``init_client``: call it once, before the first AI invocation. +An explicit ``True`` or ``False`` on a factory would override this default. + +Run from the repository root: + + python -m examples.capture_content "" +""" + +from __future__ import annotations + +import json + +import examples.register # noqa: F401 – side-effect: populate global_registry +from examples.utils import new_context, write_output +from launchdarkly_ai_server import ( + SDKOptions, + config, + configure, + global_registry, + init_client, + shutdown, +) + +_DEFAULT_KEY = "launch-darkly-documentation-summarizer" +_DEFAULT_USER_INPUT = "What is the LaunchDarkly AI SDK?" + + +async def run(key: str, user_input: str) -> None: + response = await config( + key=key, + registry=global_registry, + ).invoke(user_input, new_context()) + + print(json.dumps(response, indent=2, default=str)) + write_output(response) + + +async def _main(key: str, user_input: str) -> None: + configure(options=SDKOptions(capture_content=True)) + await init_client() + try: + await run(key, user_input) + finally: + await shutdown() + + +if __name__ == "__main__": + import asyncio + import sys + + from dotenv import load_dotenv + + load_dotenv() + key = sys.argv[1].strip() if len(sys.argv) > 1 else _DEFAULT_KEY + user_input = sys.argv[2].strip() if len(sys.argv) > 2 else _DEFAULT_USER_INPUT + asyncio.run(_main(key, user_input)) From 87c3d67e7fe803ee1f546deeb69f5fe062512bfa Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 14 Oct 2026 22:18:04 +0000 Subject: [PATCH 2/3] fix(examples): load dotenv before building provider clients The capture example imported the registry at module load, so provider clients were constructed before .env was read. --- examples/capture_content.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/capture_content.py b/examples/capture_content.py index 495332fd..8f7d25e8 100644 --- a/examples/capture_content.py +++ b/examples/capture_content.py @@ -15,7 +15,6 @@ import json -import examples.register # noqa: F401 – side-effect: populate global_registry from examples.utils import new_context, write_output from launchdarkly_ai_server import ( SDKOptions, @@ -41,6 +40,14 @@ async def run(key: str, user_input: str) -> None: async def _main(key: str, user_input: str) -> None: + # Provider clients snapshot API keys at construction. Load .env before + # examples.register builds them, then set the process default before any + # AI call. The handlers themselves take no capture_content argument. + from dotenv import load_dotenv + + load_dotenv() + import examples.register # noqa: F401 – side-effect: populate global_registry + configure(options=SDKOptions(capture_content=True)) await init_client() try: @@ -53,9 +60,6 @@ async def _main(key: str, user_input: str) -> None: import asyncio import sys - from dotenv import load_dotenv - - load_dotenv() key = sys.argv[1].strip() if len(sys.argv) > 1 else _DEFAULT_KEY user_input = sys.argv[2].strip() if len(sys.argv) > 2 else _DEFAULT_USER_INPUT asyncio.run(_main(key, user_input)) From f5fa6fae8a23d8187ba8f631ebfb98d75e08ebc4 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 15 Oct 2026 18:04:17 +0000 Subject: [PATCH 3/3] docs(examples): run content capture through main.py Drop the example's own entrypoint and register it with the other examples. --- examples/capture_content.py | 50 ++++++------------------------------- main.py | 2 ++ 2 files changed, 10 insertions(+), 42 deletions(-) diff --git a/examples/capture_content.py b/examples/capture_content.py index 8f7d25e8..dfce35db 100644 --- a/examples/capture_content.py +++ b/examples/capture_content.py @@ -3,33 +3,25 @@ The handlers in the global registry are built with no ``capture_content`` argument. They read the process default when they run. ``configure`` is -separate from ``init_client``: call it once, before the first AI invocation. -An explicit ``True`` or ``False`` on a factory would override this default. +separate from ``init_client``: ``main.py`` initializes the client, and this +example calls ``configure`` once before the first AI invocation. An explicit +``True`` or ``False`` on a factory would override this default. -Run from the repository root: - - python -m examples.capture_content "" +Usage (via main.py): + python main.py capture-content "" """ from __future__ import annotations import json +import examples.register # noqa: F401 – side-effect: populate global_registry from examples.utils import new_context, write_output -from launchdarkly_ai_server import ( - SDKOptions, - config, - configure, - global_registry, - init_client, - shutdown, -) - -_DEFAULT_KEY = "launch-darkly-documentation-summarizer" -_DEFAULT_USER_INPUT = "What is the LaunchDarkly AI SDK?" +from launchdarkly_ai_server import SDKOptions, config, configure, global_registry async def run(key: str, user_input: str) -> None: + configure(options=SDKOptions(capture_content=True)) response = await config( key=key, registry=global_registry, @@ -37,29 +29,3 @@ async def run(key: str, user_input: str) -> None: print(json.dumps(response, indent=2, default=str)) write_output(response) - - -async def _main(key: str, user_input: str) -> None: - # Provider clients snapshot API keys at construction. Load .env before - # examples.register builds them, then set the process default before any - # AI call. The handlers themselves take no capture_content argument. - from dotenv import load_dotenv - - load_dotenv() - import examples.register # noqa: F401 – side-effect: populate global_registry - - configure(options=SDKOptions(capture_content=True)) - await init_client() - try: - await run(key, user_input) - finally: - await shutdown() - - -if __name__ == "__main__": - import asyncio - import sys - - key = sys.argv[1].strip() if len(sys.argv) > 1 else _DEFAULT_KEY - user_input = sys.argv[2].strip() if len(sys.argv) > 2 else _DEFAULT_USER_INPUT - asyncio.run(_main(key, user_input)) diff --git a/main.py b/main.py index 0bbaefe1..09d17ff2 100644 --- a/main.py +++ b/main.py @@ -6,6 +6,7 @@ Examples: python main.py agent launch-darkly-documentation-summarizer "What is the LaunchDarkly AI SDK?" + python main.py capture-content launch-darkly-documentation-summarizer "What is the LaunchDarkly AI SDK?" python main.py streaming launch-darkly-documentation-summarizer "Summarise feature flags in 3 bullets" python main.py judge launch-darkly-documentation-summarizer "What is the LaunchDarkly AI SDK?" python main.py graph my-agent-graph "What is the LaunchDarkly AI SDK?" @@ -44,6 +45,7 @@ EXAMPLES: dict[str, str] = { "agent": "examples.agent", + "capture-content": "examples.capture_content", "streaming": "examples.streaming", "graph": "examples.graph_example", "graph-history": "examples.graph_history",