← All AI Engineer talks

AI Engineer Europe 2026

Why Rust is the Ideal Language for Vibe-Coding

Read the talk

Why Rust’s Constraints Help Coding Agents

First-attempt runnable code is a weak target for agentic development. Rust’s compiler gives an agent enforceable constraints and specific feedback for its next revision.

From a talk by Daniel Szoke

Before you start: Basic familiarity with type checking, async code and shared mutable state is helpful; no prior Rust experience is required.

Which language should a coding agent use?

Which language should you choose for agentic coding? Python, JavaScript and TypeScript are familiar answers. Daniel Szoke, who introduces himself as Sentry’s Rust SDK maintainer, begins with that conventional choice. When Szoke asked ChatGPT, it recommended Python first and JavaScript/TypeScript second. His own experience put TypeScript ahead.

The GitHub report he cites ranked TypeScript first by distinct monthly code contributors in August 2025. That measures participation, not language quality or coding-agent performance. GitHub’s suggested explanation—that AI-assisted development helped drive the change—is a suspected influence, not established causation. The question is what makes these languages attractive to agents in the first place.

Purple gradient slide quoting GitHub on TypeScript becoming its most-used language in August 2025, surpassing Python by roughly 42,000 contributors.
GitHub’s contributor-count quotation places TypeScript ahead of Python.
0:160:37
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

0:16 · section reference included

Why familiar languages produce quick first drafts

The advantages are practical, and most help human programmers as well as agents:

  • Familiarity: These are common languages, often learned early, with conventions that both people and models recognize.
  • Existing building blocks: Frameworks, libraries and examples let a new application start from established components.
  • Fast iteration: Python and JavaScript make it easy to run code and inspect its behavior. TypeScript adds compilation to JavaScript, but still supports a quick edit-and-run cycle.
  • Typing support: Type annotations can catch misuse before execution, although TypeScript’s any and Python’s Any weaken those checks where they are used.

Together, familiar patterns and relatively few constraints make it easier for a model to produce runnable code on its first attempt. That is an appealing starting experience: generate something, run it, observe the result and iterate.

Slide with four advantages and a concluding sentence saying LLMs often output runnable code in these languages on the first try.
Familiarity, libraries, fast scaffolding and typing support favor TS/JS and Python.
2:042:22
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

2:04 · section reference included

Runnable code is not the same as reliable code

Ease of generation and reliable behavior are different objectives. A language that readily accepts a model’s first draft also gives that draft room to contain mistakes. The same flexibility that makes JavaScript, Python and TypeScript convenient can admit both obvious errors and subtle ones. Adding types helps, but type checking alone does not address every failure class, and escape hatches reduce its coverage.

Szoke expects model errors to persist even as models improve, pointing to their nondeterministic behavior. The engineering requirement is therefore familiar: just as software needs safeguards against mistakes by capable human programmers, agent-generated software needs safeguards against model mistakes. Better generation does not remove that requirement.

3:343:55
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

3:34 · section reference included

What tests and review can establish

Tests and code review provide substantial protection, but relying on them alone leaves several distinct gaps.

SafeguardRemaining limitation
Tests written after implementationAn agent may reproduce implementation details in its tests instead of checking the intended behavior independently.
Test-driven developmentWriting tests first does not make exhaustive coverage of input combinations practical.
Agent-written tests and agent reviewThe model can make mistakes in the verification work too.

A failing test exposes an incorrect result for the case it exercises. Passing a collection of cases generally cannot prove that every possible input produces the right output. Tests remain useful evidence; they are not a universal proof of correctness.

5:315:51
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

5:31 · section reference included

Plausible code can fail in unfamiliar ways

Yuval Noah Harari’s Nexus gives Szoke another way to frame the problem. The book follows information networks from early human societies through the printing press and internet to AI. As Szoke recounts it, Harari prefers “alien intelligence” because “artificial” understates how differently these systems operate from human minds.

For coding, the implication is that a model’s mistakes may not resemble the ones a human reviewer expects. Token prediction can produce sensible variable names, clear comments and convincing structure while concealing a subtle bug. It can also produce an unnecessary heuristic where a direct check would be both simpler and more reliable. The appearance of careful programming is not evidence that the underlying decision is sound.

6:406:54
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

6:40 · section reference included

Add a deterministic checking layer

Szoke invokes Murphy’s Law to motivate another layer of protection: if a failure remains possible, repeated opportunities may eventually expose it. Human review, agent review and testing can reduce that risk. A deterministic check can go further for the particular rules it enforces, rejecting a violation every time it encounters one.

Rust is built around many such constraints. It is a compiled language designed for safety and performance, aiming at C and C++’s performance class while enforcing rules around types, memory and concurrent access. Successful compilation increases confidence that covered classes of errors are absent; it does not establish that the application implements the right behavior.

Editor’s note: Rust’s safety guarantees depend on safe Rust and correctly implemented unsafe abstractions. Unsafe operations carry obligations that programmers must uphold; unsafe does not disable every compiler check.

The compiler’s explanations matter as much as its refusal to accept a program. Rust aims to make diagnostics useful to learners by explaining what went wrong and often how to repair it. Those explanations also give a coding agent concrete context: compile, inspect the rejected operation and revise the code around the identified constraint.

8:469:04
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

8:46 · section reference included

The constraints an agent must satisfy

Strict type safety removes the TypeScript-style any escape hatch from ordinary type checking. An agent cannot resolve a mismatch simply by declaring that the value should be exempt from those checks.

Explicit absence replaces a universal null value with Option<T>. A possibly missing value is represented as Some(value) or None, so accessing its payload requires working with that optional representation.

Editor’s note: This does not guarantee graceful handling of missing values. unwrap() and expect() are safe Rust methods that compile but panic when called on None.

Fearless concurrency extends checking to data used across threads. The compiler constrains which values can move between threads and which can be shared, preventing unsafe combinations from being accepted in safe code. These are only some of Rust’s enforced properties, but concurrency provides a particularly concrete example of how a constraint becomes useful feedback for an agent.

White slide listing strict type safety, no universal null value, fearless concurrency and additional guarantees, beside an orange Rust crab.
Rust safety guarantees: strict typing, null safety and fearless concurrency.
10:5311:08
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

10:53 · section reference included

A shared counter that the compiler rejects

The example begins with a counter initialized to zero and concurrent work that increments it. After all 100 increments complete, the intended counter value is 100. The problem is the choice of shared state: the types support shared mutation within one thread, but do not provide synchronization for access across threads.

In an implementation that permits unsynchronized access to shared memory, a counter could intermittently finish with the wrong total. Inside a larger application, locating that race could be difficult. Szoke uses TypeScript as the contrast, then points out that Rust rejects his example before execution.

Editor’s note: The JavaScript analogy requires an appropriate shared-memory setup, such as workers accessing a SharedArrayBuffer. Ordinary async tasks on one JavaScript thread do not by themselves create this cross-thread data race.

The diagnostic concerns an async future that cannot safely be sent between threads. Rust expresses that requirement through Send: a type implementing it permits ownership to transfer between threads. Although Szoke describes the concurrent work as threads, the diagnostic does not imply a separate operating-system thread for every increment.

Further down, the compiler identifies the captured value: Rc<RefCell<i32>> is not Send. Rc supplies shared ownership within a thread, while RefCell permits mutation through runtime borrow checking; neither combination supplies the cross-thread synchronization this counter needs. The central constraint can be isolated without choosing an async runtime:

rust

use std::{cell::RefCell, future::Future, rc::Rc};

fn increment(counter: Rc<RefCell<i32>>) -> impl Future<Output = ()> + Send {
    async move {
        *counter.borrow_mut() += 1;
    }
}

The return type requires a Send future, but that future captures an Rc. This is the mismatch the agent needs to repair, rather than a vague instruction to make the program safer.

For the same counter, a thread-safe replacement is Arc<Mutex<i32>>: Arc provides shared ownership across threads, and the mutex protects the read-modify-write operation. Expressing that repair in the increment function gives:

rust

use std::{future::Future, sync::{Arc, Mutex}};

fn increment(counter: Arc<Mutex<i32>>) -> impl Future<Output = ()> + Send {
    async move {
        let mut value = counter.lock().expect("counter lock poisoned");
        *value += 1;
    }
}

The diagnostic has narrowed the agent’s next decision to a concrete one: choose a shared-state representation suitable for the concurrency the program requires.

12:0612:19
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

12:06 · section reference included

Evaluate the repair loop, not just the first draft

More constraints make Rust harder for a model to get right on its first attempt. That cost looks different when the model operates inside an agent that can use tools and revise its work:

  1. Generate or modify the Rust code.
  2. Compile it.
  3. Inspect failures and their explanations.
  4. Repair the identified problems and compile again.

A compiler error is actionable feedback, not merely a failed generation. Each error potentially prevents a production bug. The qualification matters: static checks can conservatively reject valid programs too, so compiler errors are not a one-for-one count of bugs avoided.

Szoke argues that compilation is faster than asking an AI agent to review the code. He presents that as a practical comparison, without a timing benchmark. The more fundamental distinction is what each check establishes: the compiler enforces its covered rules, while an agent reviewer may overlook their violation. Review still has a place, including for behavior beyond the compiler’s guarantees. The proposed workflow keeps it and adds a deterministic layer that the agent can use on every revision.

14:2214:35
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

14:22 · section reference included

The sponsored closing

Szoke closes by explicitly identifying the talk as sponsored and returning to his Sentry affiliation. The closing promotion offered attendees three free months of Sentry’s Business plan through a QR code. He also mentions agent monitoring features and invites attendees to the downstairs booth to ask about Sentry or discuss the talk.

15:3615:52
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

15:36 · section reference included

Resources

From the talk

  • Yuval Noah Harari's history of information networks, from early societies to artificial intelligence.

  • Official Rust SDK and integrations for reporting application events, errors and panics to Sentry.

  • Explains Rust's rules for transferring ownership and sharing references across threads, including Rc, RefCell, Arc and Mutex.

  • Reference and examples for optional values, payload extraction, fallback values and panic behavior.

  • A practical tutorial on async tasks, ownership and Send bounds, with examples of compiler rejection involving Rc.

Read the complete timestamped transcript
  1. 0:00

    [upbeat music] My name is Daniel Szoke.

  2. 0:16

    I'm, uh, the Rust SDK maintainer at Sentry, and I wanna tell you why I think Rust is the ideal language for vibe coding. So, the conventional wisdom on what language to use for agentic coding or vibe coding, however you refer to it, um, it's...

  3. 0:37

    Rust is probably not one of the first things you think of. Um, you know, maybe you think, you know, probably ChatGPT has a good idea what's the best agentic coding language, given that it's also a- an agent of some sort.

  4. 0:53

    And it would tell you that there's no single number one language, um, but that Python is probably the top language. Um, and as a strong number two, it said JavaScript and TypeScript when I asked it.

  5. 1:06

    Um, and I think that this is, in at least my experience, pretty true, although I would flip the order because, um, TypeScript seems to have come out as, like, the top choice for agentic coding lately.

  6. 1:22

    And, um, so there's even this article from GitHub that came out, uh, I guess late last year, and it says that AI... Like, they think that AI has pushed TypeScript to the number one, um, language on GitHub by contributor counts at least.

  7. 1:40

    Um, so they know it's TypeScript is the number one language, and they, they strongly suspect that that's because of people using it for AI-assisted development. But why are these languages, Python, TypeScript, JavaScript, so ideal for vibe coding, um, at least in the, this sort of

  8. 2:04

    conventional wisdom? So first of all, they're common and familiar languages. Um, so they're, they're, they're usually the languages you would learn if you were learning programming from scratch. So they're easy for humans, and they also seem to be easy for LLMs.

  9. 2:22

    There's also a lot of frameworks, libraries, and examples out there, um, so that, that's helpful if you're building something new from scratch, of course, that you can build it on top of something.

  10. 2:35

    And, you know, it's helpful for humans. It's also helpful for agents.

  11. 2:40

    They're fast to scaffold and run. They're dynamic languages. They're interpreted, at least JavaScript and Python are. TypeScript, maybe there's some light compilation down to JavaScript or something. But it's pretty easy just to run it and see what it does, and then you iterate on that.

  12. 2:59

    And, uh, particularly for agents, the typing support is helpful so that the agent doesn't misuse types. Um, but, uh, yeah, there's the any type that it kind of undermines that a little bit in, in TypeScript and, and typed Python.

  13. 3:16

    But, you know, overall, these languages, LLMs, the models themselves are pretty good at outputting runnable code in the first try because these languages are simple, um, and they impose few constraints.

  14. 3:34

    So I think because of this fact that LLMs just seem to be good at writing them, people jump to these languages. Um, but I think something that a lot of people, in my experience, don't question as much is whether this is even something we want to optimize for, right?

  15. 3:55

    Um, the classic vibe coding languages are easy for the models to write, but is that even a good thing?

  16. 4:04

    My argument is that the importance of it being easy for the model to write the language is overstated, and in fact, I would even say that in some cases it's a bad thing that these languages are easy for the models to write.

  17. 4:22

    Um, the dynamic and flexible nature of the languages is what makes it easy for the agent, or for the LLM, I should say, to write JavaScript, Python, TypeScript. Um, but this same flexibility also makes it very easy to make mistakes, sometimes even obvious mistakes, sometimes less obvious mistakes.

  18. 4:45

    Adding typing is a helpful constraint, but that only gets you so far, um, because it only gives you the type safety, and also it's not a very strong type safety, um, in TypeScript or Python.

  19. 4:59

    And this is, of course, a problem because LLMs are fallible. They will always be fallible because they are, by design, non-deterministic systems. So hopefully in the future they get better at making mistakes less often.

  20. 5:15

    But I don't think this is something that would ever disappear entirely. And so just like the smartest humans make mistakes and we need to guard against human error, we're also gonna need to guard against LLM error.

  21. 5:31

    One way that folks often would do that, especially also in the conventional, uh, vibe coding languages, is adding tests. This is a huge help, but there are a lot of problems with only relying on having tests and, and code review agents.

  22. 5:51

    Um, firstly, you know, if you don't prompt the agent skillfully, it'll often write the tests after the implementation, and then you just end up testing implementation details without actually testing the behavior properly.

  23. 6:06

    Uh, even with that test-driven development, though- Tests usually can only prove incorrectness when they fail. Because it's impractical to test every single possible input combination, you can't prove that every input produces the correct output in a lot of cases.

  24. 6:29

    And then, of course, if LLMs are the ones generating the tests, they may make mistakes when writing those tests, and the same thing applies to coding review agents.

  25. 6:40

    And then kind of more on a philosophical level, right? We all know AI stands for artificial intelligence, but there's this book called Nexus I recently read, and I can highly recommend it to anyone who hasn't read it yet.

  26. 6:54

    It's from an author, Yuval Noah Harari. He's a historian, and he has kind of a unique perspective on artificial intelligence, so he's discussing human information networks all the way from Stone Ages to printing press, to internet, to now with LLMs, right?

  27. 7:16

    Um, and he thinks LLMs are really unique because it's the first time we have something that's non-human that's able to produce human language. And, um, a point he makes that really stuck with me is that he doesn't like that the A in AI is artificial because it understates how different, um, LLMs and other AI

  28. 7:40

    technologies are from how humans think, and he actually likes to call it alien intelligence instead. Um, because the internal workings of how they think at a low level is different from how we think.

  29. 7:55

    LLMs predict tokens that come in streams, and it's a very powerful mechanism of thinking, but it's not how we think. And my point here is that the failure modes might be totally unexpected to us, and I'm sure if you've done any coding with AI, you might have had a situation where you got code that looked really nice.

  30. 8:17

    It might have had sensible variable names, good comments, and whatever, but when you take a look, something might not be right. Like, there might be a subtle bug, or maybe it's relying on some heuristic when you could check the actual thing and more reliably and more easily in some cases.

  31. 8:36

    So you really need to be careful with this, with, um, LLM and agentic-based development, right?

  32. 8:46

    And then that brings me to Murphy's Law, which basically states that anything that can go wrong will go wrong eventually at some point, right? So if you are using a language without deterministic guardrails, even if you apply human review, uh, agentic review, test...

  33. 9:04

    a good testing process, if you don't have something that is a absolute deterministic guard against this, eventually you're gonna have some failures. And in these languages like JavaScript, Python, TypeScript, where you lack these guardrails a lot of the times, you're gonna have failures more often, right?

  34. 9:26

    Um, and this brings me to Rust, which is a language with many constraints. Um, and so for those of you who don't know anything about Rust or don't know that much about it, some basic background.

  35. 9:42

    It's a compiled language. It's designed with safety and performance in mind. It wants to be as fast as C and C++, but it wants to be memory-safe, type-safe, um, and basically wants to be such...

  36. 9:58

    Like, it wants to have such a strict compiler that if the code compiles, you can be reasonably confident that a lot of different types of bugs are not present in your code.

  37. 10:10

    Um, and that, that happens because the compiler is enforcing invariants like type safety, memory safety, concurrency, et cetera.

  38. 10:21

    Um, and the language tries to be very beginner-friendly. So Rust itself, I think people who haven't encountered it would kind of have the perception that it's very advanced, but they try to make the language easy to learn.

  39. 10:34

    The compiler errors give you a lot of information on what went wrong and how to fix the problem. And so they provide a lot of context, and of course, this is really helpful when AI agents compile Rust code, hit an error, and then need to fix it.

  40. 10:53

    So as I mentioned, there's a lot of safety guarantees in Rust, right? Um, first one worth mentioning is that the type safety is, is strict. You can't bypass it with some any type or an unchecked cast.

  41. 11:08

    Null safety is another big one if you've come from other languages. There's no universal null value. If you want to have an option that... or an, a type that can be empty, you need to define it explicitly as an option type, and the compiler will force you to always check that the value is there before you access

  42. 11:28

    the inner value. And fearless concurrency, which is, I think, really powerful, and it basically means that the Rust compiler will check if you have a, any multi-threaded code, that any data shared between the threads is done, that that's all done in a thread-safe way.

  43. 11:49

    And this is really just a small list. There's, there's so many more things that the Rust compiler enforces. But I just wanna give you all a quick example on fearless concurrency because I think it's, it's really powerful.

  44. 12:06

    So here's a little code example. Basically, we have a counter here, which is gonna start with a value of zero, and we're gonna create 100 threads here, um-

  45. 12:19

    And each time we're gonna take the counter and add one to this inner value. So once all these threads finish, you would expect this to have a value of 100.

  46. 12:33

    Now, there's a problem here, which is that, um, these types here, they're designed for, um, sharing mutable data, but only within a single thread. They're not synchronized for, um, multi-threaded safe access.

  47. 12:51

    Um, so in a language like TypeScript, something like this might compile, it might run, and then you would only notice the problem when every once in a while you would get a value other than 100 out of this, right?

  48. 13:06

    And it might be, especially if this is a small s- part in a bigger application, it could be very difficult to debug where this data race is occurring. But in Rust, this just doesn't compile.

  49. 13:21

    You're gonna get a compile error, and it will say, "Error: Future cannot be th- sent between threads safely." Um, this future, so this little async block in here, um, is not Send, and all Send means is safe to be sent between threads, and it's not.

  50. 13:41

    So this error isn't that helpful, but if you scroll down in the error message, it'll explain further, and this is what's gonna be really helpful to your AI agent because it says, "Oh, the value here, this counter value that was captured, it's not Send.

  51. 13:59

    It has type RcRefCell i32, and that's not Send." And so if your AI agent, when it just compiles your project, it'll get this compiler error, and it can immediately go and change this to a thread safe type, of which there's, there's plenty in, in Rust.

  52. 14:22

    Um, so of course, all these, uh, constraints come with a trade-off. Rust is harder for LLMs to ru- get right on the first try because there's so many rules they need to follow.

  53. 14:35

    But I think this is a good thing. Um, that's because it's not just LLMs that write code. We put the LLM in an AI agent. It's in a loop.

  54. 14:45

    It can do things autonomously. And AI agents are very well-suited to be able to compile their code, check any failures, and then go and fix them. And every compile error, um, is potentially a bug that you avoid in your production code.

  55. 15:03

    So, um... And, and with the Rust compiler, like something I hear sometimes, people complain that compile times are slow. But I guarantee you that it's faster than letting an AI agent review your code, and it might not even find all the errors that the Rust compiler is guaranteed to find.

  56. 15:25

    I still think you should use, use it, of course, but it's good to have this, um, additional element of safety, I guess.

  57. 15:36

    And of course, this is a sponsored talk, and I'm from Sentry, so this is the little marketing slide. Um, you should try us out if you don't already. This QR code would give you three months for free of our business plan.

  58. 15:52

    Um, we have agent monitoring features. We have a booth downstairs. Come by, feel free to ask questions about Sentry, or if you wanna talk to me about the talk, you can also come by and I'm happy to chat.

  59. 16:05

    Thank you. [clapping] [outro music]