[HN Gopher] Go is a good fit for agents
___________________________________________________________________
Go is a good fit for agents
Author : abelanger
Score : 94 points
Date : 2025-06-04 12:14 UTC (5 days ago)
(HTM) web link (docs.hatchet.run)
(TXT) w3m dump (docs.hatchet.run)
| behnamoh wrote:
| > concurrency
|
| by that logic Elixir is even better for agents.
|
| also the link at the bottom of the page is pretty much why I
| ditched Go: https://go.dev/blog/error-syntax
|
| The AI landscape moves so fast, and this conservative, backwards
| looking mindset of the new Go dev team doesn't match the forward
| looking LLM engineering mindset.
| jclulow wrote:
| I don't use either Go or LLMs, but isn't the point of LLMs that
| they write the tedious boilerplate for you? What's the value in
| a small syntactic improvement if the computer is generating it
| all anyway?
| behnamoh wrote:
| Elixir's concurrency model is fundamentally different than
| Go's; it's not just syntax difference.
| kamikaz1k wrote:
| by your logic, only considering part of the argument is as good
| as considering the entire argument.
| guywithahat wrote:
| Well elixir doesn't produce goroutines (managed threads), they
| produce "lightweight processes" which have isolated memory.
| These are more expensive to grow and aren't as easy to share
| data between one another, although they're much more fault
| tolerant as a result. It could be better however the underlying
| concurrency model in Elixir is relatively unique
| regularfry wrote:
| It's been a while since I was in the weeds on this, but if I
| remember correctly they're strictly speaking _mostly_
| isolated. Binaries above a certain size share storage between
| processes, so moving big blobs between processes is cheap.
| guywithahat wrote:
| They also have their own system to share data between
| processes, although I haven't used it. Generally though
| it's a unique tool that's not always interchangeable with
| Go
| bheadmaster wrote:
| > also the link at the bottom of the page is pretty much why I
| ditched Go: https://go.dev/blog/error-syntax
|
| Funnily, it's also one of the reasons I stay with Go.
|
| Error handling is the most contraversial Go topic, with half
| the people saying it's terrible and needs a new syntax, and
| half saying it's perfect and adding any more syntax will ruin
| it.
| sorentwo wrote:
| Absolutely!
|
| Elixir's lightweight processes and distribution story make it
| ideal for orchestration, and that includes orchestrating LLMs.
|
| Shameless plug, but that's what many people have been using
| Oban Pro's Workflows for recently, and something we
| demonstrated in our "Cascading Workflows" article:
| https://oban.pro/articles/weaving-stories-with-cascading-wor...
|
| Unlike hatchet, it actually runs locally, in your own
| application as well.
| jerf wrote:
| If it had a larger learning base, quite possibly.
|
| Erlang possibly even more so. The argument that pure code is
| generally safer to vibe code is compelling to me. (Elixir's
| purity is rather complicated to describe, Erlang's much more
| obvious and clear.) It's easier to analyze that this bit of
| code doesn't reach out and break something else along the way.
|
| Though it would be nice to have a language popular enough for
| the LLMs to work well on, that was pure, but that was also
| _fast_. At the moment writing in pure code means taking a
| fairly substantial performance hit, and I 'm not talking about
| the O(n log n) algorithm slowdowns, I mean just normal
| performance.
| tptacek wrote:
| Elixir is great for agents.
| achileas wrote:
| This makes me want to build agents in Elixir now
| tolerance wrote:
| As a functionally-code-illiterate-vibe-coder, I can confirm that
| LLMs are good at writing Go code.
| dpe82 wrote:
| As a highly-literate developer with almost 30 years of
| experience, I can also confirm that LLMs are very good at
| writing Go.
| odyssey7 wrote:
| AI engineers will literally invent a new universe before they
| touch JavaScript.
|
| The death knell for variety in AI languages was when Google rug-
| pulled TensorFlow for Swift.
| kweingar wrote:
| Why is JS particularly good for agents?
| EGreg wrote:
| Because it integrates great with browsers and people know the
| language already for node.js and the packages in npm can work
| for both?
| wild_egg wrote:
| A uniform language and ecosystem has been the siren song of
| JS for over a decade and I've yet to see it work out in any
| meaningful way.
|
| Use whatever you like.
| EGreg wrote:
| I mean, what else do you use to run things in the
| browser?
|
| Pouchdb. Hypercore (pear). It's nice to be able to spin
| up JS versions of things and have them "just work" in the
| most widely deployed platform in the world.
|
| TensorflowJS was awesome for years, with things like
| blazeface, readyplayer me avatars and hallway tile and
| other models working in realtime at the edge. Before
| chatgpt was even conceived. What's your solution,
| transpile Go into wasm?
|
| Agents can work in people's browsers as well as node.js
| around the world. Being inside a browser gives a great
| sandbox, and it's private on the person's own machine
| too.
|
| This was possible years ago:
| https://www.youtube.com/watch?v=CpSzT_c7_UI&t=10m30s
| wild_egg wrote:
| > what else do you use to run things in the browser?
|
| I do my best to run as little in the browser as possible.
| Everything is an order of magnitude simpler and faster to
| build if you do the bulk of things on a server in a
| language of your choice and render to the browser as
| necessary.
| dpe82 wrote:
| Avoiding JavaScript like the plague that it is, is not unique
| to AI engineers.
|
| -Someone who has written a _ton_ of JS over the past... almost
| 30 years now.
| rednafi wrote:
| This is the way.
|
| JS is a terrible language to begin with, and bringing it to the
| backend was a mistake. TS doesn't change the fact that the
| underlying language is still a pile of crap.
|
| So, like many, I'll write anything--Go, Rust, Python, Ruby,
| Elixir, F#--before touching JS or TS with a ten-foot pole.
| guywithahat wrote:
| I wish we had better concurrency models in the ML world. I tried
| doing some ML in Go a few months back and it's basically
| impossible; there's just no library support and doing anything
| requires a gRPC call or a wrapper. Python has limitations and C++
| has a tendency to make everything too verbose.
| kamikaz1k wrote:
| > High concurrency
|
| > Share memory by communicating
|
| > Centralized cancellation mechanism with context.Context
|
| > Expansive standard library
|
| > Profiling
|
| > Bonus: LLMs are good at writing Go code
|
| I think profiling is probably the lowest value good here, but
| would be willing to hear out stories of AI middleware
| applications that found value in that.
|
| Cancelling tasks is probably the highest value good here, but I
| think the contending runtimes (TS/Python) all prefer using 3P
| libraries to handle this kind of stuff, so probably not the
| biggest deal.
|
| Being able to write good Go code is pretty cool though; I don't
| write enough to make a judgement there.
| eikenberry wrote:
| > Bonus: LLMs are good at writing Go code
|
| Good at writing bad code. But most of the code in the wild is
| written by mid-level devs, without guidance and on short
| timelines.. i.e bad code. But this is a problem with all
| languages, not just Go.
| jasonthorsness wrote:
| Go is great for command-line tools because of library support and
| fast-starting single-binaries. While most of the benefits in the
| article are also shared with JavaScript, I wonder if the CLI
| advantage will help and whether command-line agents will become a
| thing ("grepllm"?)
|
| The language of agents doesn't matter much in the long run as
| it's just a thin shell of tool definitions and API calls to the
| backing LLM.
| skybrian wrote:
| For long-running, expensive processes that do a lot of waiting, a
| downside is that if you kill the process running the goroutine,
| you lose all your work. It might be better to serialize state to
| a database while waiting? But this adds a lot of complexity and I
| don't know any languages that make it easy to write this sort of
| checkpoint-based state machine.
| Karrot_Kream wrote:
| Temporal is pretty decent at checkpointing long-running
| processes and is language agnostic.
| sorentwo wrote:
| That's the issue with goroutines, threads, or any long running
| chain of processes. The tasks must be broken up into atomic
| chunks, and the state has to be serialized in some way. That
| allows failures to be retried, errors to be examined, results
| to be referenced later, and the whole thing to be distributed
| between multiple nodes.
|
| It must in my view at least, as that's how Oban
| (https://github.com/oban-bg/oban) in Elixir models this kind of
| problem. Full disclosure, I'm an author and maintainer of the
| project.
|
| It's Elixir specific, but this article emphasizes the
| importance of async task persistence:
| https://oban.pro/articles/oban-starts-where-tasks-end
| ashishb wrote:
| > For long-running, expensive processes that do a lot of
| waiting, a downside is that if you kill the goroutine, you lose
| all your work.
|
| This is true regardless of the language. I always do a
| reasonable amount of work (milliseconds to up to a few seconds)
| worth of work in a Go routine every time. Anything more and
| your web service is not as stateless as it should be.
| abelanger wrote:
| OP here - this type of "checkpoint-based state machine" is
| exactly what platforms which offer durable execution primitives
| like Hatchet (https://hatchet.run/) and Temporal
| (https://temporal.io/) are offering. Disclaimer: am a founder
| of Hatchet.
|
| These platforms store an event history of the functions which
| have run as part of the same workflow, and automatically replay
| those when your function gets interrupted.
|
| I imagine synchronizing memory contents at the language level
| would be much more overhead than synchronizing at the output
| level.
| tptacek wrote:
| This is also how our orchestrator (written in Go) is
| structured. JP describes it pretty well here (it's a durable
| log implemented with BoltDB).
|
| https://fly.io/blog/the-exit-interview-jp/
| abelanger wrote:
| Nice! It makes a lot of sense for orchestrating infra
| deployments -- we also started exploring Temporal at my
| previous startup for many of the same reasons, though at
| one level higher to orchestrate deployment into cloud
| providers.
| skybrian wrote:
| Yep, though I haven't used them, I'm vaguely aware that such
| things exist. I think they have a long way to go to become
| mainstream, though? Typical Go code isn't written to be
| replayable like that.
| abelanger wrote:
| I think there's a gap between people familiar with durable
| execution and those who use it in practice; it comes with a
| lot of overhead.
|
| Adding a durable boundary (via a task queue) in between
| steps is typically the first step, because you at least get
| persistence and retries, and for a lot of apps that's
| enough. It's usually where we recommend people start with
| Hatchet, since it's just a matter of adding a simple
| wrapper or declaration on top of the existing code.
|
| Durable execution is often the third evolution of your
| system (after the first pass with no durability, then
| adding a durable boundary).
| carsoon wrote:
| I actually working on an agent library in golang and this is
| exactly the thought process I've come up with. If we have
| comprehensive logging we can actual reconstruct the agents
| state at any position. Allowing for replays etc. You just need
| the timestamp(endpoint) and the parent run and you can build
| children/branched runs after that.
|
| Through the use of both a map that holds a context tree and a
| database we can purge old sessions and then reconstruct them
| from the database when needed (for instance an async agent
| session with user input required).
|
| We also don't have to hold individual objects for the
| agents/workflows/tools we just make them stateless in a map and
| can refernce the pointers through an id as needed. Then we have
| a stateful object that holds the previous
| actions/steps/"context".
|
| To make sure the agents/workflows are consistent we can hash
| the output agent/workflow (as these are serializable in my
| system)
|
| I have only implemented basic Agent/tools though and the
| logging/reconstruction/cancellation logic has not actually been
| done yet.
| awinter-py wrote:
| oh my god these things run on a gpu don't they? they have nothing
| to do with golang? to the extent they run on a cpu they're heavy;
| we're not like solving the c10k problem with agents
| achileas wrote:
| Agents don't typically, and any LLM they're calling is likely
| hosted remotely.
| _QrE wrote:
| I'm not sure how valid most of these points are. A lot of the
| latency in an agentic system is going to be the calls to the
| LLM(s).
|
| From the article: """ Agents typically have a number of shared
| characteristics when they start to scale (read: have actual
| users): They are long-running -- anywhere from
| seconds to minutes to hours. Each execution is expensive
| -- not just the LLM calls, but the nature of the agent is to
| replace something that would typically require a human operator.
| Development environments, browser infrastructure, large document
| processing -- these all cost $$$. They often involve
| input from a user (or another agent!) at some point in their
| execution cycle. They spend a lot of time awaiting i/o or
| a human.
|
| """
|
| No. 1 doesn't really point to one language over another, and all
| the rest show that execution speed and server-side efficiency is
| not very relevant. People ask agents a question and do something
| else while the agent works. If the agent takes a couple seconds
| longer because you've written it in Python, I doubt that anyone
| would care (in the majority of cases at least).
|
| I'd argue Python is a better fit for agents, mostly because of
| the mountain of AI-related libraries and support that it has.
|
| > Contrast this with Python: library developers need to think
| about asyncio, multithreading, multiprocessing, eventlet, gevent,
| and some other patterns...
|
| Agents aren't that hard to make work, and you can get most of the
| use (and paying users) without optimizing every last thing. And
| besides, the mountain of support you have for whatever workflow
| you're building means that someone has probably already tried
| building at least part of what you're working on, so you don't
| have to go in blind.
| tptacek wrote:
| That's true from a performance perspective but, in building an
| agent in Go, I was thankful that I had extremely well-worn
| patterns to manage concurrency, backlogs, and backpressure
| given that most interactions will involve one or more
| transactions with a remote service that takes several seconds
| to respond.
|
| (I think you can effectively write an agent in any language and
| I think Javascript is probably the most popular choice. Now,
| _generating code_ , regardless of whether it's an agent or a
| CLI tool or a server --- there, I think Go and LLM have a
| particularly nice chemistry.)
| philwelch wrote:
| Go still has a much better concurrency story. It's also much
| less of a headache to deploy since all you need to deploy is a
| static binary and not a whole bespoke Python runtime with every
| pip dependency.
| TypingOutBugs wrote:
| Go is definitely better, but with uv you can install all
| dependencies including python with only curl
| ashwinsundar wrote:
| Is that what uv sync does under the hood, just curl's over
| all dependencies and the python version defined in .python-
| version?
| danenania wrote:
| I built Plandex[1] (open source CLI coding agent focused on large
| projects and tasks) in Go and I've been very happy with that
| decision.
|
| Beneath all the jargon, it's good to remember that an "agent" is
| ultimately just a bunch of http requests and streams that need to
| be coordinated--some serially and some concurrently. And while
| that sounds pretty simple at a high level, there are many subtle
| details to pay attention to if you want to make this kind of
| system robust and scalable. Timeouts, retries, cancellation,
| error handling, thread pools, thread safety, and so on.
|
| This stuff is Go's bread and butter. It's exactly what it was
| designed for. It's not going to get you an MVP quite as fast as
| node or python, but as the codebase grows and edge cases
| accumulate, the advantages of Go become more and more noticeable.
|
| 1 - https://github.com/plandex-ai/plandex
| npalli wrote:
| Agents to do what? Take ML/AI, all the infra and tools are
| Python/C++ so what exactly is the Agent going to help you with
| Go? Many such domains- gaming, HFT, HPC, Scientific Computing,
| Systems, UX, Enterprise etc. etc. Seems it really helps Go's
| sweet spot - CLI's and Networking services.
| tptacek wrote:
| Agents mostly _don 't_ run ML/AI code; they're a structured
| loop around LLM calls and exist mostly to give an LLM access to
| local tools in some application domain; think "reading my email
| for me" rather than "driving ML systems".
| achileas wrote:
| That doesn't negate what OP was saying at all, the better
| support in Python isn't for "running ML/AI code" but in
| things like agent frameworks, observability tools, SDKs, etc.
| None of which directly run AI code but are still
| helpful/necessary and for the most part better represented
| (and supported) in the Python world, although that seems like
| it's slowly changing.
| tptacek wrote:
| There are agent frameworks in most languages at this point
| so the question just comes down to "can you invoke tools
| for the problem you want to solve in that language". Yes,
| Python is really great at that. So is Go and Javascript.
|
| I think I'd condense this out to "this is not a really
| important deciding factor in what language you choose for
| your agent". If you know you need something you can only
| get in Python, you'll write the agent in Python.
| InTheArena wrote:
| I don't think I agree with the Go is good in LLMs.
|
| But outside of that - ML in go is basically impossible. Trying to
| integrate with the outside ecosystem of go is really difficult -
| and my experience has been that Claude Code is far less effective
| with Go then it is with Python, or even Swift.
|
| I ditched a project I was writing in Go and replaced it with
| Swift (this was mostly prompt based anyways). It was remarkably
| how much better the first pass of the code generation was.
| hoppp wrote:
| What if... hear me out... You learn to write code instead of
| generating it...there is a drastic improvement in code quality
| if you can actually write it.
| pantsforbirds wrote:
| I've been messing around with an Elixir + BEAM based agent
| framework. I think a mixture of BEAM + SQLite is about as good as
| you can get for agents right now.
|
| You can safely swap out agents without redeploying the
| application, the concurrency is way below the scale BEAM was
| built for, and creating stateful or ephemeral agents is
| incredibly easy.
|
| My plan is to set up a base agent in Python, Typescript, and Rust
| using MCP servers to allow users to write more complex agents in
| their preferred programming language too.
| nilslice wrote:
| you should check out the Extism[0] project and the Elixir
| SDK[1]. This would allow you to write the core services,
| routing, message passing, etc in Elixir, and leverage all the
| BEAM/OTP have to offer, and then embed "agents" written in
| other languages which are small Wasm modules that act like in-
| process plugins.
|
| [0]: https://github.com/extism/extism [1]:
| https://github.com/extism/elixir-sdk
| segmondy wrote:
| go is terrible for agents IMO great for agents? lisp and prolog.
| esafak wrote:
| Not without a supporting ecosystem!
| hoppp wrote:
| Go is a good fit for many use-cases.
| rpep wrote:
| In practice the library ecosystem is just way behind Python.
| Maybe after you're trying to optimise once you've worked out how
| to do stuff, but even the Langchain Go port is wayyyyy behind.
| carsoon wrote:
| I wrote the start to an agent library in Go. Its quite rough as
| most of it was implemented through using AI but I had a lot of
| ideas through planning/building it.
|
| 1. If you make your agents/workflows serializable you can
| run/load them from a config file or add/remove them from a
| decoupled frontend. You can also hash them to make versioning
| easy to track/immutable.
|
| 2. If you decouple the stateful object from the agent/workflow
| object you can just store that through sufficient logging then
| you can rebuild any flow at any state and have branching by
| allowing traces to build on one another. You can also
| restart/rerun a flow starting at any location.
|
| 3. You can allow for serializable tools by having a standard
| HttpRequestTool then setup cloudflare workers/any external
| endpoints for the actual toolcall logic. Removing primary server
| load and making it possible to add/remove tools without
| rebuilding/restarting.
|
| Given this system in golang you can have a single server which
| supports tens of thousands of concurrent agent workflows.
|
| The biggest problem is there isn't that many people who are
| working on it. So even if you can make agents 100x more efficient
| by running in Go it doesn't really matter if cost isn't the
| biggest factor for the final implementations.
|
| The actual compute/server/running costs for big AI Agent
| implementation contracts is <1%, so making it 100x more efficient
| doesn't really matter.
| vergessenmir wrote:
| Go is great for concurrency. Not quite there for agent support.
| The problem isn't performance or message passing it's the agent
| middleware i.e logging, tracing, retries, configuration
|
| You need a DSL either supported in the language or through
| configuration. These are features you get for free in python and
| secondly JavaScript. You have to write most of this yourself in
| go
| prats226 wrote:
| So far bigger bottleneck I have found in writing agents is in
| scaling integrations and not the for loop for agent. Lack of
| libraries for go is a really big challenge.
| huqedato wrote:
| Following the article's logic, Elixir is a better fit for agents.
| Ideal I would say.
| crawshaw wrote:
| We have been having good luck writing Go with an agent. Sketch is
| mostly written with itself. (There is special Go handling built
| into the agent, e.g. automatically running gofmt/goimports after
| files change.) https://github.com/boldsoftware/sketch
| paxys wrote:
| Every single feature of an "agent" they have described is
| just...generic software development. Writing loops. if/else
| statements to branch execution paths. Waiting on input. Spawning
| child processes and communicating with them. Running CPU-bound
| operations (like parsing).
|
| So every discussion about the "best" programming language is
| really you telling the world about your favorite language.
|
| Use Go. Use Python. Use JavaScript. Use whatever the hell else
| you want. They are all good enough for the job. If you are held
| back it won't be because of the language itself.
| abelanger wrote:
| For an agent that executes locally, or an agent that doesn't
| execute very often, I'd agree it's arbitrary.
|
| But programming languages make tradeoffs on those very paths
| (particularly spawning child processes and communicating with
| them, how underlying memory is accessed and modified, garbage
| collection).
|
| Agents often involve a specific architecture that's useful for
| a language with powerful concurrency features. These features
| differentiate the language as you hit scale.
|
| Not every language is equally suited to every task.
| gyudin wrote:
| It is not. Human coding languages and paradigms revolve around
| solving problems related to issues that human struggle with. We
| need AI coding languages that are easy to read and verify by
| humans, but should solve problems that AI agents struggle with.
| arthurcolle wrote:
| Erlang is a way better fit for a distributed agent orchestration
| layer. You have a ton of dependencies, over network and maybe in
| userspace, you have a lot of inter-operability and reliability
| constraints, you want to hotswap code and capabilities at
| runtime, without degrading the overall system performance. And
| you get networking/distribution/async message passing for free
|
| https://github.com/arthurcolle/agents.erl
|
| I consider myself an expert in this relatively niche domain and
| welcome follow up, critiques, and even your most challenging
| problems. I love this area and I think distributed systems are
| coming back in a big way in this new era!
| hosh wrote:
| I came here to say that too.
|
| It already does well coordinating IoT networks. It's probably
| one of the most underestimated systems.
|
| The Elixir community has been working hard to be able to run
| models directly within BEAM, and recently, have added the
| capability for running Python directly.
| arthurcolle wrote:
| Haha I wrote https://github.com/stochastic-thread/snek.ex 10
| yrs ago
|
| What are they doing with Python on the BEAM these days? I'm
| OOTL
| throwawaymaths wrote:
| https://github.com/livebook-dev/pythonx
| debarshri wrote:
| I agree.
| mountainriver wrote:
| Rust is a way better option, not sure why it isn't being
| mentioned.
|
| The issue with Go, is as soon as you need to do actual machine
| learning it falls down.
|
| The issue with Python is that you often want concurrency in
| agents. Although this may be solved with Pythons new threading.
|
| Why is Rust great? It interops very well with Python, so you can
| write any concurrent pieces into that and simply import it into
| py, without needing to sacrifice any ML work.
|
| I'll be honest Go is a bit of an odd fit in the world of AI, and
| if thats the future I'm not sure Go has a big part to play
| outside of some infra stuff.
| rednafi wrote:
| Not every post about Go needs to mention Rust. Rust has its
| niche and so does Go. Both kind of suck at AI.
|
| LLM researchers care about neither since Rust comes with its
| own headache: learning curve, slow compilation, weak stdlib,
| and Go's FFI story is just sad. It's still Python or GTFO.
|
| That said, Go is great to whip up "agents" since it's a nicer
| language to write networking and glue code, which is what
| agents are. Other than a few niche groups, I've seen a lot more
| agents written in Go than in Rust.
| lunarcave wrote:
| Agents easily spend >90% of their time waiting for LLMs to reply
| and optionally executing API calls in other services (HTTP APIs
| and DBs).
|
| In my experience the performance of the language runtime rarely
| matters.
|
| If there ever was a language feature that matters for agent
| performance and scale, it's actually the performance of JSON
| serialization and deserialization.
| fritzo wrote:
| In my experience, the 2nd most costly function in agents (after
| LLM calls) is diffing/patching/merging asynchronous edits to
| resolve conflicts. Those conflict resolution operations can
| call out to low-level libraries, but they are still quite
| expensive optimization problems, compared to serialization etc.
| the_arun wrote:
| I have same bunch of reasoning for Java. The concept of Notebooks
| won the hearts of developers I guess.
___________________________________________________________________
(page generated 2025-06-09 23:00 UTC)