Model or dataset
MagnivOrg/prompt-layer-library avatar
MagnivOrg/prompt-layer-library

PromptLayer: tracing off, cache at zero, and a vendored plugin tree in the wheel

🍰 PromptLayer - Maintain a log of your prompts and OpenAI API requests. Track, debug, and replay old completions.

784 stars95 forksPythonApache-2.0

At a glance

What is it?
The Python client for PromptLayer ships its two headline capabilities disabled by default, commits two lock files for a single build tool, and packages a Claude plugin vendor tree that only one Makefile target can rebuild.
Who is it for?
PromptLayer suits a Python team that already holds a PromptLayer account and wants one client to cover template fetches, request logging and trace export instead of hand written HTTP calls. It does not suit a checkout that needs the OpenRouter path on Python 3.9, a build that treats third party plugin files as auditable source, or a service that cannot accept a None where an exception belongs.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 47 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The first command in the file needs a package that is installed further down

The opening bash block sits above the Installation heading, inside the AI coding agents section, and it runs a console script:

bash
promptlayer setup

That script ships inside the distribution, so the first instruction a reader copies cannot work until they have run an install line several paragraphs later. Four variants follow it:

bash
promptlayer setup skills
promptlayer setup mcp
promptlayer setup --agent cursor --agent claude
promptlayer setup --force

What the command writes is worth reading before running it. It installs the PromptLayer docs skill plus a second skill named `sdk-eval-builder` into Cursor and Claude Code, and adds a Docs MCP server entry pointing at `https://docs.promptlayer.com/mcp` to their project configs. The `--agent` flag narrows which editors are touched and `--force` overwrites what an earlier run left behind, so a second invocation on the same checkout is a replace rather than a merge.

The claude-agents extra packages a vendor tree and one target can rebuild it

The optional integration does more than import a module. pyproject.toml carries an include list that reaches inside the package namespace and pulls a vendored tree into both build formats. Its three entries name `promptlayer/integrations/claude_agents/vendor/vendor_metadata.json`, a recursive glob rooted at `promptlayer/integrations/claude_agents/vendor/`, and `promptlayer/integrations/claude_agents/vendor/trace/.claude-plugin/plugin.json`, each with `format = ["sdist", "wheel"]`. So a wheel carries foreign files under the project's own name, one of them a `.claude-plugin` manifest. The runtime dependency behind it is optional and bounded, `claude-agent-sdk` at `>=0.1.45,<1.0.0`, installed with `pip install "promptlayer[claude-agents]"`. Regeneration is a single Makefile target and nothing else:

make
.PHONY: vendor-claude-agents-plugin
vendor-claude-agents-plugin:
	@test -n "$(PLUGIN_SRC)" || (echo "PLUGIN_SRC is required"; exit 1)
	python scripts/vendor_claude_agents_plugin.py --source "$(PLUGIN_SRC)"

That target aborts with `PLUGIN_SRC is required` when the variable is empty. A reader who installed from an index never holds the upstream plugin source, so the vendored copy in the wheel is the only one they get.

Two lock files sit beside one build tool and every target calls poetry

The root listing contains `poetry.lock` and `uv.lock` together. The build configuration is Poetry, with `name = "promptlayer"`, `version = "1.5.16"`, a single author entry and the usual URL block pointing at the Python SDK guide, the homepage, the repository and its issues tracker. Every Makefile target reaches for poetry and none mentions uv:

make
.PHONY: lint
lint:
	poetry run pre-commit run --all-files

Two resolvers pinning the same dependency graph is ordinary during a migration, but only one of them has an entry point here, and the version a user ends up with is read from `[tool.poetry]` rather than from either lock file. The root also carries an `__init__.py` next to the `promptlayer/` package directory, which makes the checkout root itself importable, and a `conftest.py` at root rather than inside `tests/`. Alongside them sit `.devcontainer/`, `.editorconfig`, `.pre-commit-config.yaml` and a `scripts/` directory, which is where the vendoring script above lives.

The Makefile env guard binds to set -a and not to the test run

The test target expands one variable, and that variable is worth reading closely:

make
RUN_TEST := test -f .env && set -a; . ./.env; set +a; poetry run pytest

The `&&` binds only `test -f .env` to `set -a`. Everything past the first semicolon is unconditional, so on a checkout with no `.env` file the sourcing line fails, `set +a` still runs, and `poetry run pytest` starts anyway with none of the variables exported into it. The file test guards a single builtin rather than the test command. Both `test` and `test-sw` expand the same variable, the latter appending `-vv --sw --show-capture=no`, which means a developer who keeps a populated `.env` runs a different environment from everyone who does not, and nothing in the output says so.

throw_on_error swaps the exception for a None the quick start never checks

`throw_on_error: bool = True` is the switch here that turns a failure into a value. The default raises PromptLayer exceptions, and setting it to False makes the same methods return `None` for many API errors. The quick start then reads:

python
prompt = pl.templates.get(
    "support-reply",
    {
        "input_variables": {
            "customer_name": "Ada",
            "question": "How do I reset my password?",
        }
    },
)

print(prompt["prompt_template"])

There is no None check between the call and the subscript, and the async sample has the same shape behind an `await`. That is correct code for the default. Set `throw_on_error=False` to keep a logging outage off the request path and the failure simply moves one frame away, from the call that raised to the consumer that subscripts. Cache invalidation sits on the same resource, so a template that failed to fetch and a template that was never fetched arrive as the same value.

Tracing and template caching are two separate opt-ins that both start disabled

`enable_tracing: bool = False` turns on OpenTelemetry export to PromptLayer and, when the tracing extra is present, auto-instruments whichever provider SDKs are already installed in the process: OpenAI and Azure OpenAI across Chat Completions, structured output parsing, Embeddings and Responses in sync, async and streaming form, Anthropic and Anthropic Vertex Messages, Google GenAI in both Gemini Developer and Vertex modes, and the Botocore Bedrock Runtime Converse and InvokeModel calls. `cache_ttl_seconds: int = 0` leaves in-memory prompt template caching inactive until the value is greater than 0. The instrumentors need their own install:

bash
pip install "promptlayer[otel-genai-instrumentation]" openai anthropic google-genai boto3

Two finer controls sit beside them. `tracing_providers` defaults to all supported providers and accepts an empty iterable to export spans without provider SDK auto-instrumentation. `tracer_provider` accepts an application owned tracer provider in place of the PromptLayer managed default, and `client.traceable()` covers functions the instrumentors never see.

One declared Python floor hides two OpenTelemetry ranges and a missing package

The declared floor is `python = ">=3.9,<4.0"`, and three OpenTelemetry packages carry two constraint rows each:

toml
opentelemetry-api = [
    {version = "^1.26.0", python = ">=3.9,<3.10"},
    {version = ">=1.44,<2", python = ">=3.10,<4.0"},
]

The same pairing repeats for `opentelemetry-sdk` and `opentelemetry-exporter-otlp-proto-http`. So 3.9 interpreters stay on the 1.26 line while 3.10 and later require 1.44 or newer, which is a wide span for one package family inside a single release. `openrouter` is gated to `python = ">=3.10,<4.0"` with an inline comment saying the OpenRouter SDK needs Python 3.10 and that the gate keeps installs on 3.9 from failing, followed by a note that it remains a required rather than optional dependency on supported interpreters. On 3.9 the install succeeds and that package is simply absent.

The resource surface is wider than the log of OpenAI requests the blurb promises

The client exposes `client.templates` for retrieval, listing, publishing and cache invalidation, `client.run()` and `client.run_workflow()`, `client.log_request()`, `client.track` for metadata and scores, `client.group`, `client.traceable()`, `client.skills` for pull, create, publish and update, `client.tables.sheets.scorecards`, and provider proxies at `client.openai` and `client.anthropic`. Every method has an async version, which is why both `nest-asyncio` and `aiohttp` sit in the required dependency list next to `httpx`. Four environment variables are read: `PROMPTLAYER_API_KEY`, required unless the key is passed as `api_key=`, `PROMPTLAYER_BASE_URL` defaulting to `https://api.promptlayer.com`, `PROMPTLAYER_OTLP_TRACES_ENDPOINT` for the `/v1/traces` target, and `PROMPTLAYER_TRACEPARENT`. Templates are fetched from the service rather than the checkout, and `examples/tracing/` is the only example directory present.

Editorial conclusion

PromptLayer suits a Python team that already holds a PromptLayer account and wants one client to cover template fetches, request logging and trace export instead of hand written HTTP calls. It does not suit a checkout that needs the OpenRouter path on Python 3.9, a build that treats third party plugin files as auditable source, or a service that cannot accept a None where an exception belongs. Check four things before adopting it. Confirm the version you resolve matches the 1.5.16 recorded in pyproject.toml, because the repository publishes no GitHub releases and the last push on the default branch was 2026-08-19. Confirm your interpreter is 3.10 or later if OpenRouter matters. Read what promptlayer setup writes into your editor configs before running it. And decide whether enable_tracing and cache_ttl_seconds are set to the values you actually want, since both arrive off.

Frequently asked questions

What does the PromptLayer Python client give you over a plain HTTP request?

PromptLayer exposes template retrieval, listing, publishing and cache invalidation, request logging, annotation helpers, skill pull and publish, scorecard tables, and proxies around the OpenAI and Anthropic SDKs. Every method also has an async version on AsyncPromptLayer.

Does the promptlayer package need an API key to run?

Yes. The api_key parameter defaults to None and falls back to PROMPTLAYER_API_KEY, and the quick start expects a key generated from PromptLayer Settings before pl.templates.get can return a template.

Is prompt tracing enabled by default in promptlayer?

No. enable_tracing defaults to False, and the OpenTelemetry instrumentors arrive only with the otel-genai-instrumentation extra. Prompt template caching is off for the same reason: cache_ttl_seconds defaults to 0 and activates only above 0.

Which Python versions does promptlayer support?

pyproject.toml declares python = ">=3.9,<4.0". The OpenTelemetry packages fall back to ^1.26.0 on 3.9 and require >=1.44 on 3.10 and later, while openrouter is gated to 3.10 and up with a comment explaining the gate.

What does promptlayer setup write into a project?

It writes the PromptLayer docs skill and the sdk-eval-builder skill for Cursor and Claude Code, and adds the Docs MCP server at https://docs.promptlayer.com/mcp to their project configs. Variants limit the run to skills or mcp, name agents with --agent, and pass --force to overwrite.

How are promptlayer versions published?

Through the package index rather than GitHub releases, which the repository has none of. pyproject.toml records version 1.5.16, and the last recorded push to the default branch was 2026-08-19.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. MagnivOrg/prompt-layer-library on GitHub
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/magnivorg-prompt-layer-library.svg)](https://hysenlabs.com/projects/magnivorg-prompt-layer-library)