{"slug": "introduction-to-openai-s-decisions-api-building-a-remote-job-finder-with-serpapi", "title": "Introduction to OpenAI's Decisions API: Building a Remote Job Finder with SerpApi", "summary": "OpenAI released its Decisions API in public beta on October 6, 2026, returning probabilities, choices, or scores from text and image inputs using the gpt-6-luna model, which OpenAI reports is about ten times faster than the Responses API. SerpApi published a tutorial building a remote job finder that fetches up to five listings via its google_jobs engine and filters them with three Decisions API question types: a predicate on fully remote work, a choice among shortlist, skip, and needs_review, and a score of weak, partial, or strong. The tutorial requires Python 3.10 or newer, uv, and OpenAI Python SDK version 3.26.0 or later.", "body_md": "OpenAI's Decisions API lets us ask questions and receive answers in fixed formats that our code can use directly.\n\nOpenAI released the [Decisions API](https://developers.openai.com/api/docs/guides/decisions) in public beta on October 6, 2026. It accepts text and images and returns a probability, a choice, or a score. The current model is `gpt-6-luna`, and OpenAI reports responses about ten times faster than through the Responses API. We can ask several independent questions about the same input in one request.\n\nWe explored a similar approach in our [Jev tutorial](https://serpapi.com/blog/getting-started-with-jev-building-a-fact-checker-with-serpapi/), where we built a fact checker that evaluates claims using search results.\n\nWe will use the Decisions API with SerpApi to build a remote job finder. We will fetch job listings using SerpApi's `google_jobs` engine and send them to OpenAI with our preferences to filter out roles that don't match.\n\n## How the Decisions API works\n\nA traditional LLM API, such as OpenAI’s Responses API, lets us send a prompt and ask the model to generate text. It could write code, draft a cover letter, or explain a topic.\n\nThe Decisions API returns answers in fixed formats. It cannot write a free-form response like a paragraph or a code snippet. We pass text or images in the `input` and describe what we want to know in `questions`.\n\nThere are three question types:\n\n| Type | How it works | Main output | \n|---|---|---|\n| Predicate | Checks whether a condition is true, expressed as a probability. | `probability` , from`0` to`1` . | \n| Choice | Selects one option from a set of choices we provide. | `choice` and`confidence` . | \n| Score | Rates the input using ordered levels we define. | `score` and`confidence` . | \n\n## What our remote job finder will do\n\nWe will use SerpApi to search for `SerpApi remote jobs` and fetch up to five listings. For this example, we’re looking for full-time, fully remote Python Developer Advocate roles. We will send each listing to the Decisions API with the following requirements:\n\nFull-time Python developer advocacy, including tutorials and example projects. Fully remote. Full-time contract roles are acceptable.\n\nFor each listing, we will ask three questions.\n\n**Predicate:** “Does this listing allow fully remote work without required office visits?”\n\n**Choice:** “Does this job meet the stated preferences?” We will define these options:\n\n- `shortlist` : The listing supports all our required preferences.\n- `skip` : The listing clearly conflicts with a requirement.\n- `needs_review` : There is no clear conflict, but a required detail is missing or unclear.\n\n**Score:** “How closely do the job’s duties and skills match the requested role?” We will use `weak`, `partial`, and `strong` as our levels.\n\nYou can change the query and preferences to look for another role. If you need to work from a particular country or time zone, include that in your preferences too.\n\n## Set up the project\n\nYou need Python 3.10 or newer, [uv](https://docs.astral.sh/uv/getting-started/installation/), a [SerpApi account](https://serpapi.com/users/sign_up), and an [OpenAI API key](https://platform.openai.com/api-keys).\n\nYou can find the full code on [GitHub](https://github.com/serpapi/tutorials/tree/master/python_projects/openai-decisions-remote-job-finder). Clone the repository, navigate to the tutorial folder, and install the dependencies:\n\n```\ngit clone https://github.com/serpapi/tutorials.git\ncd tutorials/python_projects/openai-decisions-remote-job-finder\nuv sync --locked\n```\n\nThe example uses the official [SerpApi Python package](https://serpapi.com/integrations/python) and OpenAI Python SDK. For an existing uv project, install them with:\n\n```\nuv add serpapi \"openai>=3.26.0,<4\"\n```\n\nThe Decisions API requires OpenAI Python SDK version `3.26.0` or later. The script reads `SERPAPI_API_KEY` and `OPENAI_API_KEY` from your environment. If either is missing, it asks for that key through a hidden terminal prompt. You can find your SerpApi key from the [dashboard](https://serpapi.com/dashboard).\n\n## Fetch job listings with SerpApi\n\n[SerpApi's Google Jobs API](https://serpapi.com/google-jobs-api) returns job titles, company names, descriptions, and application links. We will use the [JSON restrictor](https://serpapi.com/json-restrictor) to request only `jobs_results`.\n\n``` python\nimport serpapi\n\ndef search_jobs(query, key, country=\"us\", location=None, limit=5):\n    params = {\n        \"engine\": \"google_jobs\",\n        \"q\": query,\n        \"gl\": country,\n        \"hl\": \"en\",\n        \"json_restrictor\": \"jobs_results\",\n    }\n    if location:\n        params[\"location\"] = location\n\n    client = serpapi.Client(api_key=key, timeout=60)\n    data = client.search(params)\n    if data.get(\"error\"):\n        raise RuntimeError(\"SerpApi could not return job results for this search.\")\n\n    return data.get(\"jobs_results\", [])[:limit]\n```\n\n`q` is our search query, and `gl` selects the search country. You can also pass `location` to set a search origin. The employer's hiring restrictions still need to be checked against your preferences.\n\nWe will send each listing to OpenAI so it can compare the job’s responsibilities and working arrangement with our preferences.\n\n## Define the decision questions\n\nWe will ask OpenAI whether to shortlist the job, whether it allows fully remote work, and how closely its duties match our preferences.\n\n### Choose which jobs to shortlist\n\nOur main question uses Choice. We describe when to return `shortlist`, `skip`, or `needs_review`:\n\n```\nMATCH_QUESTION = {\n    \"type\": \"choice\",\n    \"name\": \"match\",\n    \"instructions\": (\n        \"Does this job meet the stated preferences? Check the duties, employment type, \"\n        \"remote work, and any requested country or time zone. \"\n        \"Choose skip for a clear conflict, even if other details are missing. \"\n        \"Otherwise, use needs_review if a requirement cannot be checked from the listing.\"\n    ),\n    \"choices\": [\n        {\n            \"value\": \"shortlist\",\n            \"description\": \"The listing explicitly supports all required preferences.\",\n        },\n        {\n            \"value\": \"skip\",\n            \"description\": \"The listing clearly conflicts with a required preference.\",\n        },\n        {\n            \"value\": \"needs_review\",\n            \"description\": (\n                \"There is no clear conflict, but a required detail is missing or unclear.\"\n            ),\n        },\n    ],\n}\n```\n\n`type` selects Choice. We use `name=\"match\"` to identify this question's answer later. `instructions` describes the assessment, and `choices` contains the allowed values and their definitions.\n\nThe `needs_review` option is useful when a listing is incomplete. If you require a full-time role and the listing does not state the hours, the model can return that option instead.\n\n### Check remote work and role fit\n\nWe will add a `Predicate` question for remote work and a `Score` question for the job duties. Both use the same listing, so we can send them with the Choice question in one request.\n\n```\nREMOTE_QUESTION = {\n    \"type\": \"predicate\",\n    \"name\": \"fully_remote\",\n    \"instructions\": \"Does this listing allow fully remote work without required office visits?\",\n}\n\nFIT_QUESTION = {\n    \"type\": \"score\",\n    \"name\": \"role_fit\",\n    \"instructions\": (\n        \"Rate how closely the listed duties and skills match the requested role. \"\n        \"Evaluate role content only, independently of location and working arrangements.\"\n    ),\n    \"levels\": [\n        {\"label\": \"weak\", \"description\": \"Different work, or too little role detail to assess.\"},\n        {\"label\": \"partial\", \"description\": \"Some relevant duties, but the main focus differs.\"},\n        {\"label\": \"strong\", \"description\": \"The main duties and skills match the requested role.\"},\n    ],\n}\n\nQUESTIONS = [REMOTE_QUESTION, MATCH_QUESTION, FIT_QUESTION]\n```\n\nOur Score levels run from `0` for weak to `2` for strong. The returned score can fall between them.\n\n## Send a listing to OpenAI\n\nNow we can send a job to OpenAI. We put the preferences and listing details in a dictionary, then convert it to a JSON string.\n\n``` python\nimport json\nfrom openai import OpenAI\n\nclient = OpenAI()\n\ndecision = client.decisions.create(\n    model=\"gpt-6-luna\",\n    input=json.dumps({\"preferences\": preferences, \"job\": job}, ensure_ascii=False),\n    questions=QUESTIONS,\n)\n```\n\n`json.dumps()` converts our dictionary into the text input accepted by the Decisions API.\n\n## Read the answers\n\nOpenAI returns an `answers` list. We store each answer under its question name, then read the answer to our `match` question:\n\n```\nanswers = {}\nfor answer in decision.answers:\n    answers[answer.name] = answer.model_dump()\n\nmatch = answers.get(\"match\", {})\n\nif match.get(\"type\") == \"choice\":\n    print(\"Decision:\", match[\"choice\"])\n    print(\"Confidence:\", match[\"confidence\"])\nelse:\n    print(\"This listing needs manual review.\")\n```\n\nThe `choice` field contains the decision, such as `shortlist` or `skip`. The script uses that choice as the job's status. If the API refuses this question or does not return an answer, the script marks the job as `needs_review`.\n\n## Run the remote job finder\n\nLet's run the script with our SerpApi job search and Python developer advocacy preferences:\n\n```\nuv run job_finder.py \"SerpApi remote jobs\" \\\n  --country us \\\n  --preferences \"Full-time Python developer advocacy, including tutorials and example projects. Fully remote. Full-time contract roles are acceptable.\"\n```\n\nThe default limit is five jobs from the first search page. Add `--limit 10` to assess up to ten, or `--json > results.json` to save the listings and answers to a file.\n\n## Results\n\nWe ran `SerpApi remote jobs` on October 7, 2026. The search returned five listings with SerpApi as the employer. Here are two examples from the run:\n\n| SerpApi role | Decision | Confidence | \n|---|---|---|\n| Python Developer Advocate | `shortlist` | `0.85` | \n| Public Relations Manager | `skip` | `0.97` | \n\nOpenAI shortlisted the Python Developer Advocate role and skipped the Public Relations Manager role. The Python role also received a role-fit score of `1.96` out of `2`.\n\nTry another search query and adjust the preferences for the role you want. The Decisions API uses the listing details we provide to decide how well each job matches those preferences.\n\n## More things to build with Decisions and SerpApi\n\nThe same types of questions work with other SerpApi results. You could check whether a news story concerns a company you follow or whether a shopping listing matches the product you want.\n\n### Filter competitor news\n\nUse SerpApi's [Google News API](https://serpapi.com/google-news-api) to collect stories about a company. A Predicate can check whether a story refers to the company you track. A Choice can classify relevant stories as product launches, funding announcements, or leadership changes before your application selects alerts.\n\n### Match products before comparing prices\n\nFetch listings through SerpApi's [Google Shopping API](https://serpapi.com/google-shopping-api). Ask a Choice question whether each listing matches the product model and condition you want. Your code can compare prices among the matches and keep ambiguous listings for review.\n\n## Further reading\n\nIf you’d like to explore a similar project, read our tutorial on building a fact checker with Jev and SerpApi. It uses search results and a decision model to evaluate factual claims.\n\nTo learn more about fetching job listings, see the [Google Jobs API documentation](https://serpapi.com/google-jobs-api). Our guide to Jobs search query operators also explains how to refine searches for specific titles, skills, and locations.\n\nTo start with the remote job finder, get the [full example on GitHub](https://github.com/serpapi/tutorials/tree/master/python_projects/openai-decisions-remote-job-finder), [create a SerpApi account](https://serpapi.com/users/sign_up), and try a search for the role you want next.", "url": "https://wpnews.pro/news/introduction-to-openai-s-decisions-api-building-a-remote-job-finder-with-serpapi", "canonical_source": "https://serpapi.com/blog/introduction-to-openais-decisions-api-building-a-remote-job-finder-with-serpapi/", "published_at": "2026-10-08 11:12:52+00:00", "updated_at": "2026-10-08 11:16:47.836600+00:00", "lang": "en", "topics": ["ai-products", "ai-tools", "large-language-models", "generative-ai", "developer-tools"], "entities": ["OpenAI", "Decisions API", "SerpApi", "gpt-6-luna", "Responses API", "google_jobs", "OpenAI Python SDK", "GitHub"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/introduction-to-openai-s-decisions-api-building-a-remote-job-finder-with-serpapi", "markdown": "https://wpnews.pro/news/introduction-to-openai-s-decisions-api-building-a-remote-job-finder-with-serpapi.md", "text": "https://wpnews.pro/news/introduction-to-openai-s-decisions-api-building-a-remote-job-finder-with-serpapi.txt", "jsonld": "https://wpnews.pro/news/introduction-to-openai-s-decisions-api-building-a-remote-job-finder-with-serpapi.jsonld"}}