Last week, I became a meme.

â
I posted a screenshot of some code powerful (yet unphotogenic) code that was co-created by a CopilotKit engineer and⊠by a Copilot (Cursor IDEâs).
I had a feeling it would be polarizing - and truth be told I leaned into that slightly (as youâll see belowâŠ). But didnât think it would become a niche coding meme!
But as I said last week, this is good code and I will die on that hill!
Itâs also a fascinating piece of code - and on first glance, itâs a little surprising that what it enables is even possible.
Hereâs why đ
But first: the memes
My tweet got dunked on quite a few times, by a few familiar faces:

There were some pretty funny memes:

And a few based takes:

My own overall responseâŠđ:

With the memes behind us (for now),
letâs see why: (itâs pretty interesting!)
First of all, what does this code do?
Essentially it's a if/else tree with some recursion - for figuring out the types of variables in user code during build time.
(in other words itâs a conditional, recursive type expression).
Worth noting off the bat - that type expressions code doesnât actually run as part of the application - and so cannot contain if/else blocks, only the ternary operator.
Why does it exist?
In a moment weâll get to a detailed analysis of how this code works. But first letâs see what it enables.
Background: CopilotKit
CopilotKit is an open-source platform providing plug-and-play, fully customizable Copilot building blocks-
for building app-aware AI chatbots, AI Textareas, and AI agents that can interact with your app - based on application context (and quite a bit more).
You can bring your own LLM (GPT-4 by default), and as of 2 weeks ago, you can bring your own LangChains & LangGraphs too as Copilot Skills.
useCopilotAction
One of CopilotKitâs frontend features is the useCopilotAction react hook. Each component in the application can define high-level actions for Copilot interactivity.
A simple example:
a food delivery app could add support for addToCurrentOrder which specifies accepting a dishName and quantity arguments, and then allow users to ask for âa starter order for a very hungry family of 5, with 2 picky children, mostly but not only vegetarianâ.

Specifying this in code is extremely straightforward. And it works! The Copilot engine is aware of the variables, their types, etc. - and calls the handler as needed (plain typescript/javascript code)
The only problem: the type information isnât propagated into user code. dishName, quantity etc., all appear as any.
Furthermore: if users of the framework make even a minor error - e.g. if they specify the variable names in the wrong order, or with a small typo â their end-users are going to get a runtime error. đ±
This gets quite a bit worse when you go beyond the simplest case - with nested objects, arrays, etc:

What about Zod Schema?
We have a variant of this react hook which does use Zod!
But in talking to users, a significant portion of them had not used Zod before, or did not like it. Itâs cognitive overhead that we donât want to force on users.
And truth be told: I get it.
As you saw in The Screenshot⊠we like types, and we can handle the tradeoffs.
But the code below is not an ideal dev experience - especially for the uninitiated.
Zod should not be a CopilotKit adoption blocker.

A Free Lunch! (for our users)
Ironically, the whole point of this scary complex âsuperior mega brainedâ type code is⊠to let the âanti-typistsâ have their cake and eat it too.
We realized that we can provide all of the safety + convenience benefits of Zod to those who choose plain JSON schemas - with zero overhead for users of the framework.
And all it takes is⊠30 lines of conditional recursive type dust in the framework.
In the service of making *user-code* as simple and pedestrian as possible - good framework code can â and routinely does â pull a few tricks.
Framework engineers know this!
(What about debugging, etc? As youâll see below, this code is really not so complex; it is hard to write, but itâs not too hard to read. But furthermore type expressions are structurally some of the safest code imaginable: they only affects types, are verified by the compiler, and they even get âcompiledâ out of existence on the executable code.)
Hereâs what this code enables, as you can see in the image below:
- type information is propagated â
- variables can be specified in any order (they match on names, not positions) â
- typos are statically called out as type errors â

- This also works recursively with objects and arrays: â

As framework authors, our users' dev experience >> our own dev experience. We can handle 30 lines of complex type code (that we understand well). The upside is a magical dev experience for thousands of devs every day. Obviously, this is the right tradeoff.
Bonus: render
By the way, you might have noticed the render function sitting after the handler. Yes: actions can render arbitrary react components into the chat window.
And of course: the action types continue to hold over there (with even more structure - e.g. they are automatically designated as optional when the function status is âstill-streamingâ).
Special call-out to Aceternity UI (open-source)- we made the sexy function preview component below in minutes, just for this post)
THE CodeâŠđ„
The dunks and the memes were honestly hilarious.
Good job fellas đ

But for all the geniuses who dunked on the codeâŠ
please indulge me a small counter-dunk:

Now, you know what we need:
To get type information out of the raw JSONs above, with support for recursion, arbitrary parameter ordering, typo detection, etc.
Letâs be honest for a moment:
how many of us could write this actual feature (not a âclose-enoughâ demo) from scratch? Even after seeing the code?
I stand by my meme- VERY few! đ (if you can do it - we are hiring).
And if few could implement it - fewer still would implement it (I certainly wouldnât).
How does it work?
Mea Culpa
First a small Mea Culpa - I am guilty!
The GitHub PR indentation makes the code appear more monolithic than it is.
In reality there 4 clearly distinct parts here - and the code is not that hard to understand.
As I alluded to earlier⊠this is not entirely accidental. Twitter is a funny world: things need to have meme-punch or they get 0 visibility. Thatâs the game. I purposefully chose the GitHub PR screenshot (not an IDE screenshot), where indentation is less clear- I wanted a little bit of a shock factor.
So - I deserve the roast.
(Iâd hoped folks would see whatâs going on on 2nd glance. A handful did⊠đ
)
But there really is something special going on here. This is a piece of code which significantly boosts the developer experience - which would likely not have been written (by us) in a GPT-less world. So I stand by it: the intellectual ceiling is being raised.
Had the code looked visually boring at a glance (rather than striking) - it would not have done justice to this singular moment in the history of technological evolution.
Letâs look at the code:
Below is exactly the same code, with more visible indents (and 4 newlines - sue me đ).
Once again, itâs a recursive + conditional type expression.
A couple of implications of this being a type expression:
- In type expressions, if/else is not available - you have to use the ternary operator.
- All type code gets âcompiledâ out of existence on builds. Itâs entirely about the developer experience.
If you zoom out, youâll see this is a simple if / else with 4 distinct cases (implemented via the ternary operator):
- enums (one of a few fixed strings - e.g. âinternationalâ or âdomesticâ).
- a single object
- an array of objects (with/without attributes specified- subtle difference for another post)
- the base case: specific parameters, can be required or optional
The object cases recurse back on MappedParameterTypes for each of its own propertiesâ types.

A second Mea Culpa?
Truth be told, I also had another iteration of this code which is even more actually complex, but also more boring-looking version when I tweeted The Screenshot. (and â you guessed it â the Copilot helped us arrive at this version in minutes.).
Hereâs this version:

I suspect DHH would be even less happy with this code if he read through it - types galore. And yet⊠it doesnât quite pack the same visual punch. Iâd also be first to admit there are also some abstraction complexity tradeoffs here - one could argue itâs not a net improvement over the original version.
As for us?
If 30 lines of complex type code can make our usersâ dev experience substantially better - weâll take that trade any day. Most frameworks have some code of this sort (at least the good ones).
In fact I personally pushed to merge this to main asap despite a few spots for minor improvement. Meta-infra PRs of this sort have a tendency to grow stale and never be merged â unless they are merged rapidly. We are a startup, and we ship like hell - stale is not an option.
If you are excited by what human / AI collaboration can achieve, and if you leave no stone unturned in service of a better developer experience, we are hiring. Bonus points for extensive Cloud Native experience: we are building Copilot Cloud.
Personal remarks
GPT didnât come up with the core idea for how to implement this. In fact it initially resisted our engineer who had the idea - told him itâs not possible. And it didnât get it working the first time either (or the 3rd).
This was a deeply collaborative exercise.
Where GPT tech was helpful - is in taking the abstract core insight - and applying it while taking lots of details into account.
This makes the situation even more special if you pause to think for a moment. Todaysâ AI canât do the deep thinking for us humans - but it CAN take care of minutia at all levels of abstraction, and help us focus on the most interesting parts of our work. Truly - Steve Jobsâ âbicycle for the mindâ.
Enjoy this moment while it lasts.
Ceiling is being raised: The $1000 Prize Competition!
I said itâs good code - not that itâs perfect code.
In between the dunks, a few folks on twitter had some legitimately interesting ideas for improvements. Cause for a competition!
We actually have yet to release a public version of CopilotKit that includes this change (if you want to use it, clone master) - which makes for a natural competition deadline!
Submit a PR to our repo your best version of this code. Winner gets $1000 and eternal glory via a PR merge. Bonus points if some GPT / Copilot helps you arrive there and if you share the screenshots.
The PR must be submitted sufficiently early to make it to our next release. 1-2 weeks, but no exact date. So hurry up!
âTill next time.
â
â
â
Get notified of the latest news and updates.


%20Using%20A2A%20%2B%20AG-UI%20(8).png)

