Python application example
Retrieve a published ticket router and execute it through OpenRouter.
Retrieve the published ticket router, append a user input, and call OpenRouter. This is a complete server-side example using raw HTTP. It reports the prompt version and validates the returned team label before your application uses it.
Prepare the prompt and environment
You need Python 3.10 or later. The script uses only the standard library. Complete the ticket-routing quickstart, select an OpenRouter model route, and publish the version you want to use. The example expects User message input mode and no output schema.
Create a retrieval key and provide a separate OpenRouter API key for the application's model call. The provider bills this call to that key; it does not use PromptLens Credits or a provider secret stored in your organization.
export PROMPTLENS_RETRIEVAL_URL='https://www.promptlens.io'
export PROMPTLENS_PROMPT_ID='YOUR_PROMPT_ID'
export PROMPTLENS_RETRIEVAL_KEY='YOUR_RETRIEVAL_KEY'
export OPENROUTER_API_KEY='YOUR_OPENROUTER_API_KEY'Use https://www.promptlens.io as the API origin. Keep the retrieval and provider keys in your server environment; do not expose them through browser code.
Run the example
Download route_ticket.py, or save the complete code below under that filename:
import json
import os
import sys
from urllib.error import HTTPError, URLError
from urllib.parse import quote
from urllib.request import Request, urlopen
def required_env(name):
value = os.environ.get(name)
if not value:
raise ValueError(f"Set {name} before running this example.")
return value
def request_json(url, key, body=None):
headers = {"Authorization": f"Bearer {key}"}
data = None
if body is not None:
headers["Content-Type"] = "application/json"
data = json.dumps(body).encode("utf-8")
request = Request(url, data=data, headers=headers)
with urlopen(request, timeout=60) as response:
result = json.load(response)
if not isinstance(result, dict):
raise ValueError("Expected a JSON object response.")
return result
def main():
base_url = required_env("PROMPTLENS_RETRIEVAL_URL").rstrip("/")
prompt_id = required_env("PROMPTLENS_PROMPT_ID")
retrieval_key = required_env("PROMPTLENS_RETRIEVAL_KEY")
provider_key = required_env("OPENROUTER_API_KEY")
ticket = " ".join(sys.argv[1:]).strip()
if not ticket:
raise ValueError('Usage: python3 route_ticket.py "Your ticket"')
prompt = request_json(
f"{base_url}/api/v1/prompts/{quote(prompt_id, safe='')}", retrieval_key
)
if prompt.get("inputType") != "user_message" or "outputSchema" in prompt:
raise ValueError("This example needs a User message prompt without an output schema.")
route = prompt.get("modelRouteId")
if not isinstance(route, str) or not route.startswith("openrouter:"):
raise ValueError("Select and publish an OpenRouter model route for this example.")
messages = prompt.get("messages")
if not isinstance(messages, list) or not messages:
raise ValueError("The saved prompt has no messages.")
for message in messages:
if (
not isinstance(message, dict)
or message.get("role") not in ("system", "user", "assistant")
or not isinstance(message.get("content"), str)
):
raise ValueError("Invalid saved message.")
body = {
"model": route[len("openrouter:"):],
"messages": messages + [{"role": "user", "content": ticket}],
}
if "temperature" in prompt:
body["temperature"] = prompt["temperature"]
result = request_json(
"https://openrouter.ai/api/v1/chat/completions", provider_key, body
)
choices = result.get("choices")
choice = choices[0] if isinstance(choices, list) and choices else None
message = choice.get("message") if isinstance(choice, dict) else None
output = message.get("content") if isinstance(message, dict) else None
if not isinstance(output, str):
raise ValueError("The provider returned no text answer.")
team = output.strip()
if team not in ("billing", "technical", "account"):
raise ValueError("The model did not return an allowed routing label.")
print(json.dumps({"promptVersion": prompt["version"], "team": team}))
if __name__ == "__main__":
try:
main()
except HTTPError as error:
print(f"Request failed: HTTP {error.code}.", file=sys.stderr)
sys.exit(1)
except (URLError, TimeoutError, ValueError, KeyError) as error:
print(str(error), file=sys.stderr)
sys.exit(1)Run it with a ticket:
python3 route_ticket.py "I was charged twice for my subscription."An illustrative successful result is {"promptVersion":1,"team":"billing"}. The version reflects your production label and the answer comes from your model call; it is not a guaranteed score or recorded test result.
How it works
The first request retrieves production because it has no selector. The script preserves the saved messages and temperature, appends the ticket, and maps the openrouter: route prefix to OpenRouter's model identifier. The second request uses OpenRouter's chat completion API.
The example rejects another input mode, an output schema, a non-OpenRouter route, and unexpected routing labels. When adapting it to another task, implement that task's input assembly and output validation explicitly. See input modes and structured output.
It makes a fresh retrieval on each invocation, so subsequent runs observe completed production label moves. For a long-running application, add ETag revalidation. HTTP errors and timeouts exit with a nonzero status; investigate their cause before retrying model calls that may already have incurred usage.