Most suitable programming language for the agent

The Tuist server will soon need to run tasks in remote hosts, for example to configure them as CI runners or run virtualized tasks such as signing an app. For that we need to run a piece of software in those hosts, an agent, that the server can communicate with. This has led me to think about what the most suitable language would be for the agent.

I initially thought Elixir would be a good candidate because we could build the communication on Erlang’s OTP primitives. Moreover, we could bundle it in a portable executable for macOS and Linux using the Burrito library. However, the more I thought about the architecture, the more I realized basing our a solution on OTP might not be the best idea:

  • Server-agent communication would require opening some ports to the public internet because the hosts and the server will most likely not be in the same network, and since the authentication solution of BEAM is not the safest (static cookie) this is a high risk.
  • We don’t need communication/coordination between agents (swarming, failover). Everything is coordinated centrally from the server.

Our system would be at the end of the day a job queue, which we can model with Oban, and remote agents that can pull those jobs, run tasks, and report back. With that in mind, I couldn’t avoid but think how much of a good idea using Elixir for the agent is.

At the end of the day, the agent needs to send HTTP requests to the Phoenix server, potentially establish and maintain a stateful web socket connection to send real time information, like logs, and allow the server to communicate to the agent, for example to pull a particular imagine. So if all we need is HTTP and Websocket, we don’t really take advantage of any Elixir/Erlang powerful capabilities.

This made me think Go might be a better candidate because it’s way more portable, something that’s crucial for a solution of this nature, it has a broad ecosystem of libraries and resources, it’s easy to write, and we can cross-compile easily from any host to many target OSs. Even though our focus now is Apple OSs, Linux will most likely be a hard requirement, and we’ll see with Windows.

I’m running this idea through everyone to get your thoughts and make sure we are aligned.

Some notes on Swift, Rust, and Elixir

Swift has been our default language for the CLI. I like Swift, but I don’t think the still-strong focus on Apple platforms is good. For instance, we lack some standard library APIs outside of macOS.

I also considered Rust, and while its memory management model is interesting, I don’t think we need it for this software. It’d steepen the learning curve and have little marginal value compared to Go.

And last, I considered continuing with Elixir. Having a REPL in those agents can be helpful, or using supervisors and process as error boundaries to prevent the agent from going down, but considering the role of the tool, taking jobs from a queue and run them reporting status, I don’t think we’ll benefit much from those nice Elixir/Erlang addons.

I’m aligned with using Go. That’s also the language that Dagger uses and while our needs won’t be as complex as theirs, there’s still a lot of overlap.