Agentic AI Product × Engineering Workflows

Wenjie Luo

Wenjie Luo

罗文杰

NUS MSc Civil Engineering · AI Product Builder
Reliable agents: LLM orchestration × deterministic tools × HITL × eval

One-page PDF · Grad. Jan 2027 · Singapore

Role-specific CVs and project evidence · English / 中文

About

I am Wenjie Luo, an MSc student in Civil Engineering (Transport) at the National University of Singapore. Expected graduation: January 2027. I build agentic AI products for complex workflows: the model routes, tools compute, humans confirm, evals rerun.

I work as a project engineer at Far East Facade in Singapore: 15 façade material types and inbound plans, 5 suppliers for sampling and tests, transport and site progress. In the open-source repos, Civil Buddy packs with tools computing coordinates and counts, then a human yes; malaysia-auto-ask stops if wholesale TIV versus registrations is unclear, and answers carry metric text plus table-level lineage. Its note-for-colleagues view can only be copied after a human confirms it. Both are demoable and measurable — not a live production business.

At Chery I ran competitive win/loss and VOC; at CaiXun I wrote PRDs with acceptance. Months on site made one product rule clear: an agent people will actually use has its guardrails written into the spec, not bolted on afterwards.

📍Singapore
🎓NUS MSc · Jan 2027
🏗️Far East · project engineer
🧩Agents · HITL · Eval

How I judge

Four judgments from the work.

Education

2025.08 – 2027.01 In progress

National University of Singapore

MSc Civil Engineering · Transport

Transport engineering programme; the AI coursework was taken within it.

Coursework: CEE5901QA ML Foundations, CEE5901QB Advanced AI for CEE; plus traffic planning and ITS simulation.

CEE5901QA · ML Foundations CEE5901QB · Advanced AI for CEE Traffic flow & control ITS & simulation
2021.09 – 2025.06

Chang’an University

BEng Transportation · Outstanding Engineer class

GPA 3.16 / 5.0 · about top 15% in major

Courses: Calculus I 93, university computing 90, Python. Class Youth League secretary, Sep 2024 – Jun 2025.

Experience

Material lists, supplier tests, transport and site progress — the repetitive copying is scripted away.

2026.06 – Present Project engineer Singapore · on site

Far East Facade (Singapore) | Project engineer

Semiconductor fab façade project · also an LTA building

  • Material board: 15 façade material types and inbound plans; a board tracks status and milestones.
  • Suppliers: 5 vendors; sampling and third-party tests so material arrives on schedule.
  • Site progress: tracked installation progress and quality; supported weekly meetings, monthly reports and subcontractor coordination.
  • Mail tool: Python pulls shipment and test mail, extracts arrival and inspection fields, replaces hand copying.
Material boardSuppliersPython Weekly meetings

Internships

2026.05 – 2026.06 Product

Chery International | Product Intern

  • Competitive & VOC: win/loss, styling comparison, complaint mining; 15 personas and 5 VOC reports for product definition and refresh.
  • Regional sales: bubble charts by length / price / registrations to track target-market trends.
  • KD localization: Gantt for production, logistics, and compliance nodes on the critical path.
2025.06.02 – 2025.08.04 Product

Caixun Technology | Product Intern

  • Moved a hard-to-find prize-draw entry point from the bottom of the page to a side pop-up to improve visibility; documented requirements, designed interaction prototypes, and tracked development and functional testing.
  • Independently wrote 3 PRDs and created Axure prototypes for 5 core pages; the proposals were accepted and scheduled for development. Tracked defect fixes and retesting, helping resolve more than 10 issues.
2024.12 – 2025.04 Supply chain

Expeditors | Supply-chain assistant

  • Coordination: carriers, clients, and customs brokers; issued and reviewed declarations. English on site.
  • Process: improved the existing Excel document-checking workflow, increasing processing efficiency by approximately 30%.

Inspectable engineering workflows · 2026.10

Open the demo. Inspect the decisions.

Three cases connect stateful replanning, engineering data semantics and research delivery to demonstrations, implementation choices and scope.

01 · Manufacturing planningOutage → compare → confirm → continueRecorded public replay + actual local solver 02 · IFC reviewType and unit → enrich → reopenAuthored model, complete findings and deferred work 03 · Driving-scene 3DGSOffline experiment → browser explorationActual scene, resource lifetime and archived evaluation

Read all three cases →

Selected projects

Start with three projects: GPU computing, an engineering agent and observability. More research and course work is indexed below.

More projects

Expand a title for methods, results and evidence. Course and competition projects retain their stated scope.

Keeta review analysis · Reproducible customer feedback across marketsPublic data · Text analysis
2026Personal project · Voice of customer

Public App Store reviews · Not affiliated with Keeta / Meituan

PythonSQLOllamaBootstrap
  • Analyze 2,572 reviews across seven markets in the frozen 2026-09-27 snapshot. The dashboard shows topic shares among low-star reviews, market differences and small-sample notices.
  • Compare multilingual rules with local LLM labels. An independent pandas implementation checks the SQL metrics; CI reconciles the report, dashboard and data definitions.
  • The 180 reference labels are AI-assisted, not independent human annotation. Self-selected reviews do not establish population-wide satisfaction or business impact.
LLM judge experiments — when majority votes misleadOpen source · Model evaluation
2026Open source · Model evaluation

Project Moonshot · Local models · Recomputable evidence

PythonOllamaBootstrapMoonshot
  • Compare a single judge with juries and audit how references, answer order and writing style affect grading.
  • Retain raw judgments, a pre-registered plan and offline analysis; distinguish observed results from simulated rankings.
  • Post-hoc sensitivity resamples 188 whole questions, retaining the original results for 400 items. The main contrast's 95% interval is [-0.25, 4.98] percentage points. All 20 question-cluster intervals across five seeds and two draw counts cross zero; endpoint diagnostics are in the report.
  • Use author-built test sets and deterministic labels. This independent project is not affiliated with AI Verify Foundation or IMDA.
NAVSIM ability ladder — what caps open-loop planningOpen source · AD evaluation
2026.08 – 2026.09 Open source · AD evaluation

Full navtest: 12,146 scenes / 136 logs · trained on navtrain (103,288 scenes) · three seeds per cell

NAVSIMAblationConfidence intervalsBaseline reproduction
  • Problem What is the score actually limited by — model capacity, or missing inputs? One baseline cannot tell you.
  • Approach Build a ladder where each rung adds exactly one input (acceleration, GT boxes, map centerline, human speed, logged path), score all of them on the same metric cache over 12,146 scenes, and put a paired bootstrap interval on every gain. The pipeline reproduces the published baselines: ConstantVelocity 20.7 (paper 20.6), the official EgoStatusMLP checkpoints 65.5 / 67.4 / 66.3 (paper 66.4±0.9), Human 94.6 (paper 94.8).
  • Finding 1 The map is worth about seven times what ground-truth boxes are worth: on the kinematic rung the on-route centerline is +0.296 [+0.288, +0.305]; GT boxes plus a brake are +0.040 [+0.035, +0.044].
  • Finding 2 The remaining headroom is speed, not geometry: with the path fixed to the centerline, the human speed profile is +0.049; with the speed fixed, the logged path is only +0.010.
  • Finding 3 Ground-truth perception is not a free input. Once the model already has the map, adding eight GT boxes is significantly negative in all three seeds (−0.044 / −0.031 / −0.047) while the open-loop loss barely moves (0.290 → 0.295) — the training objective cannot see this at all.
  • Calibrating the instrument, not just the subject Before any of the above: the pipeline reproduces the published baselines on the same cache — ConstantVelocity 20.7 (paper 20.6), the official EgoStatusMLP checkpoints 65.5 / 67.4 / 66.3 (paper 66.4±0.9), Human 94.6 (paper 94.8). If the pipeline does not line up, none of the findings are worth reading.
  • The usual metric cannot select a model Open-loop L1 correlates with PDMS at −0.83 in rank, which looks usable. Across the seven genuinely competitive runs it falls to −0.64 and inverts in places: dropout 0.2 fits better (ADE 0.768 vs 0.820) and scores worse (0.805 vs 0.818). Within a run, per-scene correlation never exceeds 0.38 in magnitude. It screens out broken models; it does not pick good ones.
  • Scope Sample size changes the answer: the same architecture loses to the hand rule on 563 scenes (0.527 vs 0.730) and wins on 12,146 (0.823 vs 0.785), so only the full-split numbers are quoted here. The PDM score is non-reactive simulation, not closed loop — other agents replay their logs. The privileged rungs (GT map, GT boxes) are analysis instruments, not deployable results. The official EgoStatusMLP averages 0.664 against my matching cell at 0.642; the recipes differ and I did not tune. TransFuser was not run; its published number is quoted only.
The point Open-loop loss screens out models that regularisation broke, but cannot pick the good ones — across the competitive runs its rank correlation falls to −0.64 and inverts.
cuda-fused-layernorm — hand-written CUDA that lost to Triton, and whyOpen source · GPU kernel
2026.09 Open source · GPU kernel

CUDA C++ (NVRTC) · same-card three-way comparison on a T4 · 12 shapes

CUDA C++Tritonwarp shuffleControlled comparison
  • What The Triton fused residual-add + LayerNorm kernel rewritten in CUDA C++: warp-shuffle plus shared-memory block reduction, a float64-referenced accuracy gate, a numerical-stability sweep.
  • Result On one T4 over 12 shapes: Triton 1.341× over eager, my CUDA 1.087×, CUDA vs Triton 0.812× — it loses on every shape, best 0.997×.
  • Why Triton autotunes num_warps and block size per shape; mine uses a fixed heuristic. An earlier cross-card comparison had suggested "about the same" — the same-card test reversed it, which is why the controlled comparison had to be run.
vllm-sm75-throughput — a 10× throughput collapse traced to one GEMM cliffOpen source · Inference diagnosis
2026.09 Open source · Inference diagnosis

GTX 1650 (sm_75) · refutation experiment on a T4 · fp16 GEMM

vLLMcuBLASTensor CoresAttribution
  • Problem vLLM throughput collapses about 10× on a GTX 1650. On the surface anything could be the cause.
  • Attribution fp16 GEMM bandwidth falls from 99.5 to 4.3 GiB/s going from M=1 to M=2 (0.04×): with tensor cores removed from sm_75, the cuBLAS small-M path is pathological.
  • The experiment that could have refuted it Same script on a T4 — same sm_75, same Turing, tensor cores kept: 106.7 → 88.1 GiB/s (0.83×), consistent over three shapes. One variable, a 20× difference in the ratio; the attribution holds.
  • Reported upstream The root cause is filed against PyTorch (issue #195716) and the deployment trap, with a warning proposal, against vLLM (issue #54950: --dtype half is a performance trap on tensor-core-less Turing cards); both are open.
EDA Copilot — OpenROAD flow Q&A that stops and asks when the metric is unclearOpen source · Flow Q&A
2026.09 Open source · Flow Q&A

Ran RTL→GDSII myself · 1,215-chunk corpus with line-level provenance · stop-guard ablation

OpenROAD / ORFSRAGStop guardQoR
  • Corpus Ran the full nangate45/gcd back-end flow in the official image and cut the 46 reports/logs/stage metrics plus 31 script docs into 1,215 chunks, each cited to the line.
  • Stop guard Seven structured stop codes (ambiguous metric, setup/hold unspecified, out of scope, …): 12/12 should-stop questions stop with the right code. With the guard off, all 12 are answered anyway, each with a citation — the cited wrong answer is the dangerous kind.
  • Evaluation decides After removing zero-relevance candidates from fusion, BM25 and hybrid both reach Hit@5 22/23 (0.957) on the 23-question set. Versioned results remain available, with new refusal regressions for wrong platforms, runs and unrelated questions. From my own QoR report: TNS −7.18 vs WNS −0.16, timing buffers at 18.7% of standard-cell area with WNS still unconverged.
  • Scope Example-scale design, open 45 nm library, default parameters; a digital back-end QoR report, not fab yield data.
RecAgent — an agent that runs its own MLE loopTechJam Track 2 · Autonomous ML agent
2026.09 TechJam Track 2 · Autonomous ML agent

KuaiRand-Pure · official scoring protocol · did not place

LightGBMAutoMLRanking0 manual edits
  • Problem The track does not ask for a high-scoring model. It asks for an agent that inspects, engineers features, trains, evaluates and reflects on its own.
  • Result Under the official protocol: test 0.6015 vs the FM baseline 0.5946, +0.0069 on the primary metric — in 23 scored iterations (cap 50), CPU-only, about 3.5 hours (cap 6 h).
  • The number I care about is the zero Zero manual code changes. Half the budget unused, and not a line of model code written by me — only five goal-level instructions — is what makes it an agent rather than me tuning parameters.
ByteSize — recommend only once the evidence is enoughTechJam Track 4 · Conversational search
2026.09 TechJam Track 4 · Conversational search

50,000-item catalog · 0 tokens / $0 · did not place

Value of informationLate fusionFully offline
  • Problem In multi-turn shopping dialogue the common failure is recommending as soon as the candidate pool gets small. A small pool does not mean the agent knows enough — it may just have guessed narrowly.
  • What it does Every turn asks one explicit question: is the evidence sufficient? If yes, recommend; if not, ask once more. The controller reads scenario, disclosed slots and pool size — it never inspects the remaining turn budget and never changes the ranking function.
  • Result On 800 ID-disjoint sessions it gains +60 rank-1 recommendations with zero Hit-rate loss and improves 8 of 8 shards; Hit@10 is 1.000 on the labelled public set. All of it at 0 tokens and $0.
  • Scope The holdout and the 800 sessions are my own ID-disjoint splits, not an official leaderboard.
Counterask — when answering would be a guess, the tool asks backWebMCP Challenge · Open source
2026.09 WebMCP Challenge · Open source

9,901 real menswear products (Amazon Reviews 2023) · one page, no server · 0 tokens

WebMCPSentence parsingExpected-survivors stoppingCategory-tree questions
  • What A menswear storefront whose search_products tool returns a question instead of half a ranking whenever answering would be a guess; answer_question is registered only while a question is open and unregistered once it is answered; checkout is a declarative form an agent can fill but only a person can submit. One page, no server, no model call. Verified on Chrome 152 with the WebMCP flag, driving document.modelContext directly: all eleven imperative tools plus the checkout form show up in getTools(), answer_question comes and goes natively, and checkout stops in front of the Place-order button with nothing submitted.
  • Reading a whole sentence An agent relays "a leather belt, nothing with a snap, not over $50", not two search-box words. Budget, refusals, stated attributes and "any is fine" are parsed in a fixed order, each claimed span blanked so no word is read twice. On 800 sentences generated from real product records: Hit@10 0.793 with a keyword matcher → 0.999 with the parser (0.993 on the rebuilt index, 0.991 under phrasings it was never tuned on); refusals inverted into requirements 100% → 0, budget broken in the top 10 31% → 0. 61 hand-written cases and a 4,000-sentence fuzzer run in npm test.
  • When to ask Not entropy — with multi-valued attributes the shares are not a distribution — but expected candidates removed; missing data is not a mismatch, attributes recorded on under 45% of the pool are never asked about, and a question that clears fewer than 10 candidates is not worth a turn. A "clear leader, stop asking" rule was built twice and removed twice; one step of lookahead was built, measured and left off. Each time the measurement said no.
  • Scope and credit The simulated shopper answers instantly and only tells the truth, so neither benchmark prices a person's patience or a missing attribute; coverage is the ceiling — after the index rebuild, material is recorded on 69% of products (from 56%), fit still on 9%. Teammate Cui Zixuan built an independent implementation of the same design (the cuizi-rewrite branch of the counterask repo); five of its ideas were folded back into this one.
RepostGuard — detect AI-generated images on the repost, not the originalOpen source · Image forensics
2026.08 – 2026.09 Open source · Image forensics

Frozen CLIP + DINOv2 + a 28-D forensic vector · ~110M, CPU-only · all 15 transforms

Image forensicsRobustnessBootstrap CIsLeakage control
  • Why framed this way What circulates on a platform is never the original: it has been JPEG-compressed, thumbnailed and noised. Most detectors report a clean-image number and lose it on the repost chain, so this one is scored on the transformed image.
  • Result On a held-out 1,400-image slice of SID-Set, across all 15 real repost transforms with bootstrap intervals: clean AUC 0.981, mean over 14 transforms 0.977, worst case (0.25x thumbnail) 0.968; on an unseen generator family (WildFake) 0.966 clean.
  • The finding worth reading The forensic branch is the entire cross-source generalisation — a CLIP-only probe scores 0.54 on thumbnails from an unseen generator, where chance is 0.50, and the branch lifts it to 0.79 — and it is also what collapses under noise (0.925 to 0.810 at sigma 0.10). Either half alone gives the wrong conclusion: the branch and a noise training view are worth -0.006 and +0.004 separately, and +0.014 together.
  • Showing it is not cheating Re-encoding both classes identically moves every head by at most +0.0009 AUC, and a bare blockiness scalar separates them at only 0.586 — so it is not reading JPEG history. Multi-crop TTA was implemented, measured at -0.0039 mean AUC over 15 conditions, and left off, reported as its own A/B.
  • Scope Built against the TikTok TechJam Track 5 brief and never submitted to Devpost — not a competition entry, no placement claimed. Trained on SID-Set only, so unknown commercial generators still shift the features; crop is the one scored family not yet a training view. About four days on a laptop with no GPU.
malaysia-auto-ask · Malaysia auto Q&AOpen source · ask-data
2026.08 Open source · ask-data

SQLite · fixed SQL templates · 30+8 eval cases

SQLlineageHITLEval
  • Why When business asks who sells well, some mean association wholesale (TIV) and some mean registrations — two numbers that do not match. First tell which set is being asked, then produce the table, so one sentence does not get two answers.
  • What A sentence comes in; it only answers wholesale, registrations, or share that are already defined. A frontline page shows year sales cards; a note for colleagues copies only after a confirm checkbox.
  • How If wholesale vs registrations is unclear, or the question is “last month”, “luxury cars”, or a year not in the database, it stops and asks a person — it does not guess a number. Self-test: 30 questions; 22 that should return numbers are all correct; 8 stop (26.7%).
Run locally python scripts/serve.py · open the desk page
LP / MIP from scratch — the model matters more than the solverOpen source · Operations research
2026.09 Open source · Operations research

Two-phase simplex + branch and bound + real Gomory cuts · cross-checked against HiGHS · 29 tests

Linear programmingInteger programmingSimplexCutting planes
  • The main result One problem — minimum fleet size for a fixed timetable — written two ways. The assignment formulation has a totally unimodular constraint matrix, so the LP relaxation is integral and branch and bound closes in a single node. The big-M formulation gives the identical answer but its bound collapses from 3.0 to 1.0 and it explores 21 to 31 nodes. An order of magnitude, decided at modelling time.
  • How big should big-M be A measurable decision, not a habit: tightening M from 10000 to each variable's own capacity moves the relaxation bound 1086.54 to 970.51 and the node count 19 to 5, with the optimum unchanged at 953.
  • The textbook warning is real On Beale's 1955 degenerate example, Dantzig pricing cycles and has not terminated after 203 iterations; Bland's rule converges in 9. The shipped default is Dantzig with an iteration cap that restarts under Bland, locked by a test. On the Klee-Minty cube, Dantzig takes exactly 2^n - 1 iterations (7 / 15 / 31 / 63 / 127 for n=3..7), to the step.
  • Two negative results carry it First, cuts are not free: three knapsacks go 17/27/35 nodes to 1, but n=12 is the counterexample — the bound does improve (163.44 to 160.33) and the tree still grows from 29 to 31. Second, cut validity is checked against the definition rather than by reading the code: enumerate all 5,376 integer points and assert none was cut off. An earlier fake cut failed exactly that test.
  • Scope Written on 2026-09-08; it corresponds to no past coursework or job. The largest instances are an 80x120 dense LP, 14 binaries and an 8-trip multi-depot problem, on a dense tableau simplex that does not scale; column generation is not implemented — I read about it, which is not the same as having done it. "Slower than HiGHS" is false on small instances and only reaches 32x at 80x120.
Campus shuttle routing — testing a claim that could not be falsified where it was madeOpen source · Time-dependent routing
2026.09 Open source · Time-dependent routing

23 nodes / 58 directed edges, time-dependent · four solvers cross-checked over 600 queries · 37 tests

Time-dependent shortest pathCross-validationTail latencyMap matching
  • Correctness does not rest on one solver A binary-heap Dijkstra, A*, a label-correcting reference and brute-force enumeration agree across 600 cross-checked queries; A* expands 42.48% fewer nodes and upper-bound pruning saves another 20.41%, staying optimal on 600/600. Brute force is the only independent oracle — the other two share an assumption and, on a constructed non-FIFO network, were wrong together by 38 minutes.
  • Isolate the variable before concluding "A binary heap brings this to O(|E| + |V| log |V|)" cannot be falsified on 23 nodes, where barely a dozen get expanded. So the heap was isolated on deterministically generated grid networks: its speedup grows from 1.56x at 100 nodes to 17.03x at 4,900, with A*'s saving rising from 20.0% to 38.3%. The claim has no support at the size it was made; it holds at ten thousand nodes.
  • "Under 50 ms" needs its method attached Same code: with connection reuse the p99 is 0.44 ms at concurrency 1 and 17.7 ms at 16; with a fresh TCP connection per request it becomes 515 ms — 29x worse, and all of it in connection setup, since solving itself has a p99 of 0.035 ms. The p50 lies: the fresh-connection row has the better p50 while its tail is already in seconds.
  • Fleet size is not continuous It is a ceiling function of cycle time over headway, so it drops in steps: a 26.81 min peak loop on a 4 min headway with a 3 min turnaround needs 8 vehicles, and removing one requires a 6.75% cut in cycle time — a 6% cut removes none. "Travel time down x%" and "n fewer vehicles" are separate claims.
  • Scope This is a September 2026 rebuild, not the original 2024 coursework. The original traces and code were never archived, so this repo deliberately does not reproduce the figures quoted from it. The network and the speed history are synthetic. What is rebuilt is the method and its checkability: when asked what the denominator of that 98.7% was, or how the 50 ms was measured, the answer is here.
Flooded multimodal networks: DEM, SUMO, LLM agentsNUS · CE5001
2026 NUS · CE5001

Course project · report PDF

CE5001 decision framework
SUMOLLMEval
  • Situation Bus and car routing under flood. Network, demand and inundation were not on one map; a larger model is not automatically the answer on dense vs sparse streets.
  • Task Build a comparable evaluation pipeline; simulate bus and car separately; use experiments to decide when rules suffice and when to use a model.
  • Action ~3,500 lines / 10 modules. Rules, persona-augmented rules, a local small model, and a cloud model — 200 simulation runs with paired seeds. Bus data: 793 service-direction pairs, 5,201 stops.
  • Result At Marina (H=2.5 m, GPS-off), the rule policy reduced mean resilience-loss area (RTA) by 62.2% versus no rerouting; on sparse nets, the model reached similar impact with far fewer actions. Report PDF on this site.
AYE weaving: counts, simulation, ramp meteringNUS · CE5203 group
2026 NUS · CE5203 group

Group 12 · public repo

AYE weaving simulation and ramp metering
YOLOv11SUMO
  • Situation: AYE westbound Exit 9→11 weaving jams at peak. Task: calibrate on counted traffic, then compare VSL, ramp metering, and both.
  • Action: 43 min peak and 60 min off-peak video at 4 stations; SUMO 7 nodes / 6 edges; 12 experiments. Weaving capacity ~5,060 veh/h.
  • Original course report: ramp metering cut peak network total time loss 22.7% and weaving delay 7.7%. The public repository now includes the controller and 12 rerun records; new SUMO results are reported separately from the historical figures.
Traffic coordination: approve / reject onlyNUS · CE5212 course
2026 NUS · CE5212 course

Course project · decision and grounding layers are open source

Three-layer LLM traffic coordination
LLMSUMO
  • Situation: letting the model rewrite the network produced state hallucination. Task: rules propose; the model only approves or rejects.
  • Action: SUMO net 1.4 km², calibrated on 2,874 measured speeds; 645 commuters (time-sensitive 35% / price-sensitive 40% / information-poor 25%).
  • Result: of 180 coordination ticks, 137 (76%) never reached the model; the 43 that did were all approved, none rejected — so the honest claim is “three quarters of the decisions do not need it”, not that the model caught anything. Direct invention hallucinated; sync calls slowed the sim — Bus 95 delay +2.2 min. Course lab, not a production KPI.

Skills

Product

PRD / acceptance Axure VOC / personas Gates & eval

Agents

Tools compute / humans confirm Grok Build · Claude DeepSeek API Whitelisted SQL Metrics / table lineage

Site & supply chain

Material board / suppliers Outlook pull Customs coordination Rhino (basic)

Engineering background

SUMO / TraCI Python CEE5901 ML

Campus

🏛️

Class Youth League secretary

2024.09 – 2025.06

Ran class sessions and volunteering; helped peers with job resources. University “outstanding member” award. Other undergrad posts omitted.

Contact

📧
📞
📍
Location Singapore

The approach stays the same: tools compute, humans confirm, evals rerun.
Happy to talk about agents, evaluation and engineering workflows.
NUS · graduating Jan 2027 · based in Singapore