-
-
Two runs of the same tools: identity locks at 3 of 3, then 2 of 3 twice and it asks instead of publishing. Every call on the right is real.
-
1,117 production jobs. 705 produced a report, and 42.7% of those withheld a skill level. Both denominators are shown, every time.
-
A measured visual result decides the next tool call. When the search is exhausted the loop asks a human rather than guessing.
-
OpenCV 5 and AWS components. The analysis engine is staged at build time inside our own account and is never committed or published.
What it does
ABC Vision is a badminton coaching agent that refuses to guess who you are.
Give it a match video and it finds the rallies with OpenCV 5, works out which player on court is you, and reports how you played. When it cannot do that confidently, it says so and shows you the evidence instead of publishing a number it does not believe.
It is live. Open it and watch it fail honestly:
- Simulated Alexa+ experience: https://d2xks2we90iwvv.cloudfront.net/
- The MCP server it calls: https://d2xks2we90iwvv.cloudfront.net/mcp
The conversation on the left of that page is staged. Every call on the right is real - ten JSON-RPC calls from your browser to the MCP server, each openable to its raw request and response. The page is served from the same origin as /mcp, so there is no proxy in between and nothing that could be a recording.
Why declining is the product
A skill rating is a claim about a person. Get it wrong and you have told someone they are worse than they are, in front of their club.
So this engine is built to decline, and it is not hypothetical. Over 1,117 real production jobs between 2026-09-06 and 2026-09-17:
| Outcome | Jobs |
|---|---|
| Jobs that produced a report | 705 |
| Published a skill level | 390 (55.3% of reported) |
| Declined to publish | 301 (42.7% of reported) |
| Largest single reason | too little of the player could be tracked - 213 (30.2% of reported) |
Every percentage this project reports carries both denominators, every time, because a percentage without one is a way of being wrong on purpose.
The agent loop
Identifying a player is not a classification. It is a search, and the vision result decides what gets searched next:
open_identity_session- register the detections and appearance signaturespropose_identity- anchor somewhere, propose who the subject isscore_identity_plan- how many rallies does that plan actually cover?- Below the gate? Exclude that anchor and propose again - a measured visual result changing the next tool call
- Out of anchors?
compare_identity_plans, thenexplain_identity_difference, then ask the human
The demo runs twice. First the ordinary case, where the player is on court for all three rallies: identity locks on the first attempt and analysis proceeds. Then the harder one, where the player rotates off court for the third and no assignment of detections to people can cover a rally the player was not in -- the loop tries every anchor, reaches 2 of 3, and asks rather than publishes. Only the second run branches, and the branch is the point.
OpenCV 5 on AWS, verifiable by you
Call protocol_info on the endpoint above and it returns the OpenCV version of
the process that answered:
"opencv_version": "5.0.0",
"opencv_module": "/usr/local/lib/python3.12/site-packages/cv2/__init__.py"
Opening /mcp in a browser returns a JSON-RPC error about a missing
session ID. That is correct - it is a protocol endpoint, not a web page.
The page is at /.
The scan path imports only cv2, numpy and the standard library - no
PyTorch, no ONNX Runtime, no MediaPipe - which is why real video analysis fits
in a 227 MB container instead of a multi-gigabyte one.
Architecture: CloudFront for TLS, an EC2 container behind it, pulling from a private ECR repository in our own account. The security group admits only CloudFront's origin-facing prefix list. There is no SSH and no key pair exists; administration is SSM Session Manager.
Privacy is structural, not a policy
The analysis engine is never committed and never leaves the owner's AWS account. A named allowlist of eleven files is staged at build time, the build refuses to run if anything resembling customer data reaches it, and the same refusal runs again inside CodeBuild - the last point before an image exists, because a pushed image cannot be un-pushed.
The decision trace redacts by key name and replaces identifiers with truncated SHA-256 handles, so two calls about the same video are still recognisably the same video without naming it. Redaction is covered by tests, not by convention.
What we got wrong
docs/CORRECTIONS.md in the repository lists what this project published and
then found to be wrong - including three errors the submission made about itself.
The protocol version in an earlier draft was overstated; DNS rebinding
protection was assumed to be on and was off. The conformance checker we built
for the Open Source mini challenge caught both.
It did not catch the third, and nothing else automated did either: a claim about our own failure handling that the dataset shipped in the repository contradicts. People found it by reading the claim against the data, after it had already shipped.
A project whose entire argument is about not overclaiming should publish its own corrections. So it does.
Built With
- amazon-cloudfront
- amazon-ec2
- amazon-ecr
- amazon-web-services
- aws-cloudshell
- aws-codebuild
- docker
- mcp
- model-context-protocol
- numpy
- opencv
- python
- starlette
Log in or sign up for Devpost to join the conversation.