36,301 karma · joined March 3, 2007
Data, compilers, software architecture
barry.j.kelly@gmail.com
I drink a lot of wine, but 1 full bottle is too much to have regularly. A half bottle - two generous glasses - is more reasonable, but you'll still feel it the next day. And 10 litres of alcohol puts you at 8 generous glasses a week.
I reckon this is still quite a lot of alcohol.
If energy prices are too high, industry suffers. If you let the price rise, maybe China just eats your lunch.
What's the option value vs risk of gas price rises? Gas sets the marginal price of electricity in Italy today for 60% of the year [1]
[1] https://www.terna.it/DesktopModules/AdactoBackend/API/direct... "However, the electricity system remains significantly exposed to gas price volatility, which in 2024 determined electricity prices for more than 60% of the hours."
You could build something with storage and composition out of MCP functions, but come on, have you seen how LLMs - particularly budget LLMs - try and invoke functions reliably? The amount of retries you have to hide, feedback you need to send back to the LLM about what it did wrong. Parameters get replaced with synonyms, arrays are passed for singular arguments and vice versa, structured inputs are flattened, etc.
So maybe you fine tune on interactions with your subset of MCPs, to improve reliability. But all you end up doing is reinventing a Unix-like command line, poorly.
Firecracker micro-VMs, gVisor, wasm sandboxes. There are ways to make this work that aren't heavyweight. Giving LLMs tools that they've seen how to use millions of times in training corpora just works better.
These guys are the common factor, the guys running the evals that let all the AI agents out, it looks like.
If you don't have something running somewhere, you don't have an agent, you don't have a harness. You've got a token generator, an LLM from the 2024 era.
Think of an agentic harness as like a kind of body for the LLM. It gives it primitive inputs (read_file, web_search or whatever) and primitive outputs (edit file, respond to user, etc). Give it a command line environment (in a locked down sandbox, with as few or as many tools as you prefer), and you've given it a toolbox. It can do a whole lot more, faster and more efficiently. It can compose tools together. It makes fewer transcription errors manually shifting data around. It can tame verbosity with good protections in the harness and access to grep, sed and awk.
It's really up to you how useful you want your agent to be.
Going without the sandbox means hobbling the LLM. It can do things directly but is less able to construct ad-hoc programs to deal with looping, conditionality, tame verbosity, connect tools together, and so on.
It's a choice to not give the LLM an environment. As you say, it can be necessary if you're using dumb models. I don't find it particularly worth the trade most of the time.
Peter Dicks, David Carruthers
State violence is used to ensure compliance, so that companies self-censor.
Variables can be described by types. That is, a mutable slot referencing a value can be a value itself (a reference to a reference) and we can use subtype relationships to describe it. Variables are covariant when used as inputs (i.e code reads from the variable) and contravariant when used as outputs, and invariant when used as both. You can logically supply a Box<Cat> to a vet(in Box<Animal>) routine, and supply Box<Animal> to catchAndStore(out Box<Cat>). Substitute `ref X` for `Box<X>` when using a language that can pass variables by reference.
It's orthogonal.
To be clear, I'm not suggesting blindly deploying an AI-written spike implementation to production, but rather using it to elicit information for better designs.
The fact that a probe that goes off and modifies tables X, Y and Z to achieve the feature gives information for an AI auditor to look for other uses of X, Y and Z, and discover things humans may miss, because with good guidance and a proper harness, AI is usually more persistent and thorough than people. It can turn search results into a checklist and the harness can track completion, and so on. I am far from convinced that your example would not be found via this route.
I would try and get an understanding of design space by giving a good agent a high level goal and seeing what it does, then getting a summary of the approach.
When you do this several times, especially if you give it a steer on some non-functional requirement, you can compare and contrast different approaches.
The idea isn't to prototype so much as to gather information by doing. Prototype, to my mind, suggests other things; shortcuts, stubs, incompleteness. I would actually ask agents to do the whole thing, and find out the full scope. It can be particularly useful revealing side effects.
Pair it with code auditors wearing different hats, of course.
Planning is essential but it doesn't survive contact with reality. However, AI makes contact with reality cheap! Why not use it to improve designs, by writing the design after a few implementations have already been made?
Only slightly tongue in cheek.
That means you could choose to try three (or more) genuine implementations and explore their tradeoffs, instead of making three proposals in a document with one recommended (and the other two usually only provided for contrast).
I do think the design is important to keep around - in particular, the constraints, the communication points, schema, tacit things that might not be clear in code. I am not certain that the design should precede the implementation for features below a certain size though.
Larger efforts need milestones and collaboration and will have multiple people doing implementation, so there's more need to agree schemas, APIs etc up front there.
You build in safeguards, redundancy, defense in depth, recovery systems. You build models of the system and prove characteristics about it.
Software is fundamentally automation. LLMs enable automating the construction of software itself. They're much faster and cheaper than people, and they're more unreliable. (People are unreliable too!)
The immediate challenge of these times is figuring out how to reliably construct reliable software in the large, over the longer term, reliably. This is an engineering challenge, and the only way we'll get to the other side of it is by trying to do it. Things will be rough, there will be a Cambrian explosion of techniques, most approaches will fail, and many more won't survive as models improve on quality and capability. But we'll figure it out.
Making things by hand, as in the time before agentic coding, can be engineering too, but it is not the core challenge of these times, and it will soon be a hobby, or possibly a kind of luxury good. You will no more want hand-written software than you'll want a hand-made car. It will not have the precision, performance or reliability of machine-made software.
The labyrinth symbol, as a decoration or motif in ancient Greek artifacts, isn't generally a maze, but the labyrinth of myth is. Theseus had to use thread, given to him by Ariadne, to find his way back out.
The problem with your argument is that it's a universal argument against performance. And if an argument is universal, then it doesn't have any information value.
Also Austria, perhaps Italy, but I have less direct experience there.
Small commits can often be tested faster, since irrelevant tests don't need to run.
Small commits are less risky. The smaller the delta of change, the lower the probability that something breaks.
Small commits get merged sooner; big commits take time to build up. Merging early front-loads your integration risk; merging later puts integration risk just before delivery.
Breaking a big feature into small commits means using feature flags to control whether a feature is enabled or not (since control paths will generally be incomplete). This means you separate the delivery of the code from the delivery of the feature, and has the added benefit that you can turn off a feature that has a problematic rollout without needing to redeploy code.
It uses a persistent changeid to model a change mutating over time, like Gerrit uses Change-Id in the description footer, and unlike git.
Jujutsu can be colocated with git and use .git as its backing store; every jj change revision is a git commit.
When you use jujutsu, you tend not to use branches any more, and think in terms of changes and chains of changes (i.e. stacked PRs, what Gerrit calls Relation Chains).
Jujutsu makes it very easy to work with a chain of changes (stacked PRs), letting you update commits in the middle and automatically rebasing the rest of the chain, without forcing you to interrupt work and resolve conflicts if there happen to be any (so, unlike git rebase -i with 'edit' on the commit you want to update).
IMO if you like the Gerrit workflow and the way it handles chained commits, if you switch to jj for two days of work, you'll never want to use git again.
I don't use Gimp as a 3D modeling software or a digital audio workstation. I use it to add text to a family photo. The primary storage medium is jpeg. I don't want or need anything else.
The real issues with Gimp start when you try to work with selections, transforms, cuts, crops and so on. Photoshop muscle memory doesn't transfer and it is so incredibly clunky.