Open-source decision service
Pointsman sets the switches.
Your systems ask a question. Pointsman decides which track it goes on, or calls a person when it is not sure.
{ "state": { "issue": { "title": "Login page is blank", "body": "Since this morning." } } }
{
"decision_id": "8c0f…",
"profile": "issue-triage", "profile_version": 1,
"answers": {
"team": { "value": "backend", "p": 0.9 },
"urgent": { "value": false, "p": 0.8 },
"effort": { "value": 0, "p": 0.7 }
},
"rule": 0,
"action": "auto"
}
What it does, in plain words
Many systems receive things that someone must look at first. A resident reports a closed road. A new issue arrives. A deployment seems stuck. Often the case is clear, and the system can act at once. Sometimes it is not clear, and a person should check it. Pointsman makes this first call, and it keeps a record of every call.
-
It asks fixed questions
Example: a resident reports a fallen tree on a road. What kind of closure is it? Could someone be in danger? An AI answers each question and says how sure it is, for example "danger: yes, 85 %".
-
People's rules decide
People write the rules, for example: "danger 70 % or more: urgent". The AI does not decide alone. The rules can also use facts from public data, for example whether the place is in a flood zone.
-
It answers, and keeps a record
The answer is an action, here "urgent". Pointsman saves the questions, the answers and the rule that it used. A person can correct the answers later. So you can see how often the AI was right.
publishurgentreview
You can try this example in the demo. "Review" means: a person checks it.
Decisions you can check
Many systems make small routing decisions all day: which team, how urgent, wait or stop. Pointsman makes them in one place, the same way every time, and keeps a record you can measure.
Questions with fixed answer types
Yes/no, choice and score questions. Every answer comes with its probability, so you know how sure the model is.
Policy, not prompts
Rules like team.p >= 0.85 turn answers into an action. The policy is plain config, checked when it is loaded, never evaluated as code.
A person when unsure
Below your threshold the action is review. The decision waits in a review queue; the final answer is sent, signed, to the request's callback_url if it gave one.
Versioned profiles
Questions and policy live in YAML profiles with a JSON Schema, validated in CI. Each decision records the profile version and the model.
Feedback and accuracy
People correct decisions; corrections are logged next to the answers. Measure how often each profile version was right before you raise its thresholds.
Swappable models
Models plug in through adapters. Today: Cloudflare Workers AI (clef-flash, clef), optionally through AI Gateway; your own model server, for example a local Strands Decider; and a mock model for development and tests.
Facts from public data
For a place, Pointsman can look up flood zones and the nearest evacuation site (GSI data), and the way around a closed road by car or on foot (Valhalla routing on OpenStreetMap). The AI never sees them; the rules use them, and each decision names its sources.
Decisions that build on others
A profile's requires lists earlier decisions about the same thing, read from the log by id. A final decision can be rules only, with no AI. When a person answered an earlier step, their answer counts.
The chain as a diagram
GET /v1/profiles/{id}/graph draws a chain of decisions as SVG, or exports it as DMN 1.3 for DMN tools such as dmn-js and Camunda Modeler. Pointsman uses DMN's names, not its decision tables.
How it works
One request in, one decision out. The decision log keeps everything needed to explain it later.
-
Send a state
Your system posts what it knows: an issue, a deploy event, a form. As JSON or text, to a profile.
-
Ask the questions
The profile's model answers its typed questions. If it fails, a fallback model takes over.
-
Apply the policy
The rules compare answers and probabilities. The first rule that matches picks the action.
-
Act
Your system follows the action, or a person decides.
autoreviewyour own
Pointsman for …
One engine, many kinds of work. Each use case is a set of example profiles, facts and clients that run today. Use them as they are, or as a start for your own.
Disaster response
Check reported road closures before they go on the public map. Flood zones and the nearest evacuation site come from public data for Japan; the way around comes from a routing server. Urgent and unclear reports go to a person. When people on foot are cut off from an evacuation site, the evacuation check returns alert, and the final decision makes the report urgent. Works with FIWARE through the bridge.
road-restriction-checkevacuation-access-checkroad-closure-finalDevOps
Is a quiet AWS CloudFormation deploy stuck, or only slow? A GitHub Action asks Pointsman only after the stack has been quiet for a while, and stops the deploy only after two cancel answers in a row. If Pointsman cannot be reached, nothing is stopped.
deploy-progressDeveloper workflow
Which team gets a new issue, does it block work today, how big is it? A GitHub Action labels the issue when Pointsman is sure, and asks a person when it is not. Agents can ask the same profile through MCP.
issue-triageProfiles are config
A profile says what to ask and what to do with the answers. Change a threshold with a pull request, not a prompt.
- Reviewed like code. Profiles live in your own private config repository and are published on deploy, write-once per version.
- Validated before they run. A JSON Schema and a validator check every profile in CI.
- Visible where you want. A profile can be offered to agents through MCP, or kept to the API.
id: issue-triage version: 1 title: { en: Issue triage, ja: Issue の振り分け } description: en: Route a new issue to the right team. ja: 新しい Issue を担当チームに振り分ける。 model: clef-flash fallback_models: [clef] questions: - name: team type: choice instructions: Which team should handle this issue? criteria: - { value: backend, description: "APIs, databases" } - { value: frontend, description: "Web pages, styles" } - { value: docs, description: "Documentation" } - name: urgent type: noul instructions: Does this block someone's work today? - name: effort type: score instructions: How much work does this look like? criteria: ["under an hour", "a few hours", "a few days", "more than a week"] policy: rules: - when: "team.p >= 0.85" action: auto default: review
Ask from anywhere
The same profiles, the same policy and the same decision log, whoever asks.
REST API
Decide, read a decision, send feedback, work the review queue, get a profile's decision graph. Described in OpenAPI; every client has its own API token, limited to the profiles it needs.
openapi.yaml →MCP for agents
With the Model Context Protocol (MCP), add Pointsman as a connector, and agents call decide instead of guessing. Machines use API tokens; people log in with GitHub and can correct decisions.
GitHub issue triage
A GitHub Action labels new issues from a decision, using only the labels you list. When Pointsman is not sure, or cannot be reached, the issue gets the needs-triage label (you can choose another) instead.
Deploy watch
A GitHub Action that watches a CloudFormation deploy and stops it when Pointsman judges it stuck, instead of waiting for a timeout.
actions/deploy-watch →FIWARE bridge
FIWARE is open-source software for smart-city data platforms. It uses an open data standard, NGSI-LD. The bridge connects such a platform to Pointsman. When data changes, the bridge asks Pointsman. Then it writes the decision back to the platform, so that other apps can use it. It can also create Decision and Task entities (datamodels.jp models), and a person's answer in the platform resolves the review.
Get started
Run it locally in a few minutes, with the example profiles and a mock model. No Cloudflare account needed. The mock gives fixed answers; for real answers on your machine, see docs/models.md.
-
Install
Node.js 24 and pnpm 12.
-
Start the Worker
A local decision log, then the Worker on port 8787.
-
Ask for a decision
Create a local API token and send a state to a profile.
-
Deploy your own
Copy the config repository template: your profiles, your Cloudflare account, private.
Deploy Pointsman →
# 1. install git clone https://github.com/geolonia/pointsman cd pointsman pnpm install # 2. start pnpm db:migrate:local pnpm dev # 3. ask (in a second terminal) node scripts/tokens.mjs create \ --client demo --profiles issue-triage --local export POINTSMAN_TOKEN=pm_… curl -s localhost:8787/v1/decide/issue-triage \ -H "authorization: Bearer $POINTSMAN_TOKEN" \ -H 'content-type: application/json' \ -d '{"state": {"issue": {"title": "Login page is blank"}}}'
Pointsman is not 1.0 yet: the API and the profile format may still change between 0.x releases. See the release notes, and open an issue if you try it.
Questions people ask
Short answers to questions we got about Pointsman.
Does this need a large AI model?
No. Pointsman asks the AI only a few questions, each with a fixed kind of answer: yes or no, a choice, or a score. A small, low-cost model is enough for that. By default Pointsman uses the clef models on Cloudflare Workers AI. You can also connect a model that runs on your own server.
Do I have to train a model first?
No. You write the questions and the rules, and the model answers the questions as they are. Pointsman does not train models. If you already have a model trained on your own data, you can connect it through a model server, as long as it answers the same kinds of questions: yes or no, a choice, or a score, each with a probability. Each decision keeps the AI's answers next to people's corrections, so you can see how well a model does before you let it decide more on its own.
Isn't this just a model plus a script that acts on its confidence?
That is the idea, yes. Pointsman is the script part, built so that people can read and check it:
- The rules are config that the city or team writes, not code.
- When the profile asks for them, facts about the place from public map data are added before the rules run.
- When no rule matches, the profile's default action applies, often a person's review.
- Each decision records the answers, the facts, the rule and the profile version.
- A later decision can build on an earlier one.
How is this different from GIS tools that train models on spatial data?
Those tools help you make a model, for example one that finds buildings in aerial photos. Pointsman does not make models. It takes a model's answers, adds facts about the place, and lets written rules decide what to do. The two can work together: a model trained elsewhere can answer Pointsman's questions through a model server, if it gives the same kinds of answers (yes or no, a choice, or a score, each with a probability).
What happens when the AI is not sure?
Every answer comes with a probability, and the rules compare it with a threshold you set. If no rule matches, the profile's default action applies, usually review: the decision waits for a person. The person's answer is recorded and counts in later steps.