<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tiến Trung Nguyễn</title>
    <description>The latest articles on DEV Community by Tiến Trung Nguyễn (@ntt-fei).</description>
    <link>https://dev.to/ntt-fei</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3999175%2F64f9ddaf-9d6f-44e7-843e-e6c04fe24e19.png</url>
      <title>DEV Community: Tiến Trung Nguyễn</title>
      <link>https://dev.to/ntt-fei</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ntt-fei"/>
    <language>en</language>
    <item>
      <title>I built an AI that reads contracts like a lawyer — and knows when to say "I don't know"</title>
      <dc:creator>Tiến Trung Nguyễn</dc:creator>
      <pubDate>Mon, 06 Jul 2026 08:46:29 +0000</pubDate>
      <link>https://dev.to/ntt-fei/i-built-an-ai-that-reads-contracts-like-a-lawyer-and-knows-when-to-say-i-dont-know-27pb</link>
      <guid>https://dev.to/ntt-fei/i-built-an-ai-that-reads-contracts-like-a-lawyer-and-knows-when-to-say-i-dont-know-27pb</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhaygcz99tdra09g3a0qm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhaygcz99tdra09g3a0qm.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Picture a small Vietnamese furniture exporter. A German buyer sends over a 12-page contract in&lt;br&gt;
English. Somewhere on page 7, there's a line: &lt;em&gt;"late delivery penalty: 15% of contract value."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The owner signs it. Nobody told her that Vietnamese law caps that penalty at &lt;strong&gt;8%&lt;/strong&gt; — anything&lt;br&gt;
above is simply void in court. She just agreed to a term that isn't even legal, and she'll&lt;br&gt;
negotiate her next three contracts without ever knowing she had that card in her hand.&lt;/p&gt;

&lt;p&gt;That's the problem I built &lt;strong&gt;Legal Guard&lt;/strong&gt; for, during the Qwen Cloud Hackathon (Autopilot Agent&lt;br&gt;
track). It's an AI agent that reads your contract, tells you which clauses are merely &lt;em&gt;bad for&lt;br&gt;
you&lt;/em&gt; and which are &lt;em&gt;actually illegal&lt;/em&gt;, and helps you push back — while a human approves every&lt;br&gt;
message before it goes out.&lt;/p&gt;

&lt;p&gt;Try it: &lt;a href="https://legalguard.duckdns.org" rel="noopener noreferrer"&gt;https://legalguard.duckdns.org&lt;/a&gt; · Code (open source): &lt;a href="https://github.com/trungnguyen1618033/legal-guard-PH" rel="noopener noreferrer"&gt;https://github.com/trungnguyen1618033/legal-guard-PH&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's what I learned, in plain language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 1: Don't send a senior partner to do a photocopy job
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw9to18c7770yzdvmyfp9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw9to18c7770yzdvmyfp9.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI models are like staff at a law firm. The senior partner (&lt;code&gt;qwen3.7-max&lt;/code&gt;) is brilliant and slow.&lt;br&gt;
The paralegal (&lt;code&gt;qwen-flash&lt;/code&gt;) is fast and great at simple, well-defined checks.&lt;/p&gt;

&lt;p&gt;My first version sent &lt;em&gt;everything&lt;/em&gt; to the senior partner. Analyzing one contract took minutes,&lt;br&gt;
and most of that time was spent on questions as simple as: &lt;em&gt;"Does this law article actually say&lt;br&gt;
what we claim it says — yes or no?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So I split the work the way a real firm would:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hard reasoning&lt;/strong&gt; (analyzing the contract, planning negotiation strategy) → the big model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yes/no double-checks&lt;/strong&gt; → the fast model: &lt;strong&gt;0.5 seconds instead of 23&lt;/strong&gt; — about 46× faster,
with the same answers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quick legal Q&amp;amp;A&lt;/strong&gt; → the mid-size model: 4–6 seconds instead of ~48.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One phase of the pipeline dropped from &lt;strong&gt;~4 minutes to ~7 seconds&lt;/strong&gt;. Nothing got smarter —&lt;br&gt;
the work just went to the right desk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 2: The most dangerous AI answer is the confident wrong one
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ctz0rwq94rnnor9wl8t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ctz0rwq94rnnor9wl8t.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everyone worries about AI "hallucinating" — making things up. In legal work the failure is&lt;br&gt;
sneakier: the AI cites a &lt;strong&gt;real&lt;/strong&gt; law article that simply &lt;strong&gt;doesn't say&lt;/strong&gt; what the AI claims.&lt;br&gt;
The citation checks out; the meaning doesn't. A busy reader would never catch it.&lt;/p&gt;

&lt;p&gt;Three guardrails fixed this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A second pair of eyes.&lt;/strong&gt; After the agent flags a risk, a separate AI checker gets one job:
&lt;em&gt;"Read this law article. Does it actually support this claim — yes or no?"&lt;/em&gt; If the answer is
fuzzy, we treat it as &lt;strong&gt;no&lt;/strong&gt;. In law, wrongly shouting "this clause is illegal!" is worse
than quietly asking a human to review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No zombie laws.&lt;/strong&gt; Laws get replaced constantly. Legal Guard only cites law that is
&lt;strong&gt;currently in force&lt;/strong&gt; — and if you ask "what was the rule in 2020?", it answers with the law
as it stood &lt;em&gt;in 2020&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Knowing when to say "I don't know."&lt;/strong&gt; Ask something outside its knowledge base and it says
&lt;em&gt;"I don't have enough legal basis to answer"&lt;/em&gt; — like a good lawyer saying "let me check"
instead of guessing. We treat a correct refusal as a correct answer in our tests.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We test all of this against 54 questions with lawyer-known answers, across 12 areas of&lt;br&gt;
Vietnamese law. Current score: &lt;strong&gt;54/54&lt;/strong&gt; on majority-vote (3 runs per case) — up from 87% when we&lt;br&gt;
started. One borderline case still flickers between runs (a wording match on the hosted model), so a&lt;br&gt;
single run may read 53/54 — we disclose that rather than round up to a flat 100%. The whole&lt;br&gt;
methodology is published at &lt;a href="https://legalguard.duckdns.org/trust" rel="noopener noreferrer"&gt;https://legalguard.duckdns.org/trust&lt;/a&gt; — because an AI that touches legal&lt;br&gt;
risk should show its report card.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 3: If a cheap model guards the door, test the guard
&lt;/h2&gt;

&lt;p&gt;Remember the fast "paralegal" model doing the yes/no checks? Once it gates which citations&lt;br&gt;
survive, it becomes the safety-critical part. So it gets its own exam: 16 tricky&lt;br&gt;
statements paired with real statute text — including traps like &lt;em&gt;"a 10% penalty is valid under&lt;br&gt;
this article"&lt;/em&gt; shown next to the article that says 8%. We score the fast model against both the&lt;br&gt;
correct answers and the big model's answers. Result: &lt;strong&gt;16/16 correct, 100% agreement with the&lt;br&gt;
flagship, at a fraction of the latency&lt;/strong&gt; (&lt;a href="https://github.com/trungnguyen1618033/legal-guard-PH/blob/main/evaluation/nli_report.json" rel="noopener noreferrer"&gt;test report&lt;/a&gt;). That test is what let us&lt;br&gt;
make the faster trade with a clear conscience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 4: "Autopilot" means it works while you sleep
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frkuf53hgotca4l2cpel9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frkuf53hgotca4l2cpel9.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The track is called &lt;em&gt;Autopilot Agent&lt;/em&gt; — and I took that literally. On the production server&lt;br&gt;
(one small Alibaba Cloud machine running everything in Docker), a scheduler wakes the agent at&lt;br&gt;
&lt;strong&gt;5 AM every day&lt;/strong&gt;. It checks which laws became effective, then cross-references &lt;strong&gt;every contract&lt;br&gt;
it has ever reviewed&lt;/strong&gt;: did a new decree just change an article your contract relies on?&lt;/p&gt;

&lt;p&gt;It's precise, too: a decree amending Article 9 alerts only the contracts citing Article 9 —&lt;br&gt;
no spam. And if you dismiss a false alarm once, it stays dismissed. During testing this fired&lt;br&gt;
on real data: one decree about arbitration flagged 8 stored contracts with foreign-arbitration&lt;br&gt;
clauses. Nobody asked it to. That's the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 5: A contract scanner tells you what's wrong; a copilot tells you what to &lt;em&gt;do&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5xyhlr3v1s8sshoh36d9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5xyhlr3v1s8sshoh36d9.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every contract AI flags risky clauses. The gap nobody fills for small businesses: &lt;em&gt;what do I do&lt;br&gt;
about it, from my actual bargaining position?&lt;/em&gt; So Legal Guard doesn't stop at analysis — it runs a&lt;br&gt;
&lt;strong&gt;stateful, multi-round negotiation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You tell it your leverage and whether you have a backup deal (BATNA). Then, round after round, it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;remembers what's already agreed&lt;/strong&gt; — a running "concession ledger" so it never re-negotiates a
point you already won (the naive version kept forgetting and giving ground back);&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;proposes trades, not surrender&lt;/strong&gt; — &lt;em&gt;"concede the deposit to lock arbitration in Vietnam"&lt;/em&gt; — and
screens every suggestion so it never offers away a red-line;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;knows when to walk&lt;/strong&gt; — a deterministic guardrail flips to &lt;em&gt;"recommend walk-away"&lt;/em&gt; the moment the
other side blocks a must-fix red-line &lt;strong&gt;and&lt;/strong&gt; you hold a real alternative. That rule isn't left to
the model's mood; it's enforced in code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;learns from outcomes&lt;/strong&gt; — tactics that closed real deals get weighted up next time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the line between a document scanner and a negotiation copilot — and it's the part I'd defend&lt;br&gt;
as the real moat.&lt;/p&gt;

&lt;h2&gt;
  
  
  What failed (worth as much as what worked)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A fancy tree-search retrieval method lost to the boring hybrid approach on our tests. Boring won.&lt;/li&gt;
&lt;li&gt;A graph-based reranking idea made zero measurable difference. It's in the code, switched off.&lt;/li&gt;
&lt;li&gt;Hand-tuning thresholds to fix each failing test broke a different test every time —
whack-a-mole. A structural fix (an automatic cutoff, nothing hand-tuned) is what finally held.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The one-line summary
&lt;/h2&gt;

&lt;p&gt;Spend your speed budget on reasoning, your safety budget on verification, and publish the number&lt;br&gt;
you actually measured — not the one that looks good.&lt;/p&gt;

&lt;p&gt;*Built with Qwen models on Qwen Cloud (DashScope), deployed on Alibaba Cloud ECS. Open-source&lt;/p&gt;

</description>
      <category>ai</category>
      <category>qwen</category>
      <category>legaltech</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>Which security bug should you actually worry about first?</title>
      <dc:creator>Tiến Trung Nguyễn</dc:creator>
      <pubDate>Tue, 23 Jun 2026 17:07:19 +0000</pubDate>
      <link>https://dev.to/ntt-fei/which-security-bug-should-you-actually-worry-about-first-1aik</link>
      <guid>https://dev.to/ntt-fei/which-security-bug-should-you-actually-worry-about-first-1aik</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Funlwued1z21c5dsy7fdp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Funlwued1z21c5dsy7fdp.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Which security bug should you actually worry about first?
&lt;/h1&gt;

&lt;p&gt;Imagine your security scanner hands you a list of 50 problems. Each one says: "this is bad,&lt;br&gt;
it's in this file, on this line." But it never tells you the thing that actually matters:&lt;br&gt;
&lt;strong&gt;if someone exploited this, how much of your app would break — and whose job is it to fix it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's the catch. A scanner rates a bug in some forgotten, unused file &lt;em&gt;exactly the same&lt;/em&gt; as the&lt;br&gt;
same bug sitting in the login code that half your app depends on. Same label, wildly different&lt;br&gt;
danger. So teams waste time on the harmless ones and sometimes miss the scary one.&lt;/p&gt;

&lt;p&gt;For the GitLab Transcend Hackathon, I built a little assistant to fix that. It's called&lt;br&gt;
&lt;strong&gt;Vulnerability Blast Radius&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it does, in plain words
&lt;/h2&gt;

&lt;p&gt;Think of it like this: when a bug is found, the tool doesn't just shrug and show you the line.&lt;br&gt;
It asks a simple question — &lt;em&gt;"what else in the code touches this?"&lt;/em&gt; — and follows the trail.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It &lt;strong&gt;finds&lt;/strong&gt; the security bug.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;maps the "blast radius"&lt;/strong&gt;: which other parts of the code call or rely on the broken file.
(This is the clever part — it uses GitLab's "knowledge graph," basically a map of how all the
code connects.)&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;gives it a score from 0 to 100&lt;/strong&gt;, so the genuinely dangerous bugs float to the top.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;finds the right owner&lt;/strong&gt; (the team responsible for that code).&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;writes a tidy note&lt;/strong&gt; suggesting what to do — but it only &lt;em&gt;suggests&lt;/em&gt;. A human always decides.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A real example from the demo: one bug turned out to have &lt;strong&gt;11 other files depending on it&lt;/strong&gt; → it&lt;br&gt;
scored &lt;strong&gt;96/100 (Critical)&lt;/strong&gt; → and got routed straight to the security team. That's the difference&lt;br&gt;
between "a bug somewhere" and "a bug that can really hurt you."&lt;/p&gt;
&lt;h2&gt;
  
  
  The part I'm most proud of: it doesn't make things up
&lt;/h2&gt;

&lt;p&gt;AI tools can be confidently wrong. So I made a deliberate choice: &lt;strong&gt;the score is calculated by&lt;br&gt;
plain, predictable code — not by the AI.&lt;/strong&gt; Same bug in, same number out, every single time. You&lt;br&gt;
can check the math yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Severity (critical)        40
Likelihood of exploit      16
Known to be exploited?     15
Is the code reachable?     10
How much depends on it     15
───────────────────────────────
                           96 / 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if the tool doesn't have real data yet, it says so honestly and leaves blanks — it never&lt;br&gt;
invents a number to look smart. It also asks permission before changing anything, and won't post&lt;br&gt;
the same note twice. Trustworthy beats flashy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The funny twist
&lt;/h2&gt;

&lt;p&gt;When I ran it for real, the very first bug it caught… was a small mistake &lt;strong&gt;in my own demo code&lt;/strong&gt;.&lt;br&gt;
Honestly? That's the best possible advertisement. It works on real problems, not just neat examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  A peek behind the curtain (for the curious)
&lt;/h2&gt;

&lt;p&gt;GitLab's knowledge graph is brand new, so the docs didn't always match reality. The most useful&lt;br&gt;
lesson of the whole project: &lt;strong&gt;check what the system actually does, don't trust the example.&lt;/strong&gt; A&lt;br&gt;
couple of surprises only showed up when I tested against the live system — like the fact that the&lt;br&gt;
"link" I expected between a bug and its file simply didn't exist, so I had to find another way in.&lt;br&gt;
Little things like that would have quietly broken everything if I'd trusted the manual.&lt;/p&gt;

&lt;p&gt;The result: it's open-source (MIT), backed by 94 automated tests, and published as a reusable&lt;br&gt;
agent on GitLab's AI Catalog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Have a look
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🎥 2-minute demo: &lt;a href="https://youtu.be/cEhLA04SV2c" rel="noopener noreferrer"&gt;https://youtu.be/cEhLA04SV2c&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 Code (free, MIT): &lt;a href="https://gitlab.com/gitlab-ai-hackathon/transcend/7723089" rel="noopener noreferrer"&gt;https://gitlab.com/gitlab-ai-hackathon/transcend/7723089&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🤖 The agent: &lt;a href="https://gitlab.com/explore/ai-catalog/agents/1011711/" rel="noopener noreferrer"&gt;https://gitlab.com/explore/ai-catalog/agents/1011711/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The big idea is simple: a security finding shouldn't just tell you &lt;em&gt;what's&lt;/em&gt; wrong — it should tell&lt;br&gt;
you &lt;em&gt;how much it matters&lt;/em&gt; and &lt;em&gt;who can fix it&lt;/em&gt;. Now it can.&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>devsecops</category>
      <category>ai</category>
      <category>security</category>
    </item>
  </channel>
</rss>
