aicl-lang 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aicl_lang-0.1.0/LICENSE +27 -0
- aicl_lang-0.1.0/PKG-INFO +352 -0
- aicl_lang-0.1.0/README.md +324 -0
- aicl_lang-0.1.0/aicl/__init__.py +28 -0
- aicl_lang-0.1.0/aicl/__main__.py +3 -0
- aicl_lang-0.1.0/aicl/build.py +35 -0
- aicl_lang-0.1.0/aicl/cbor_codec.py +142 -0
- aicl_lang-0.1.0/aicl/cli.py +195 -0
- aicl_lang-0.1.0/aicl/codebook.py +184 -0
- aicl_lang-0.1.0/aicl/coop.py +437 -0
- aicl_lang-0.1.0/aicl/dense.py +175 -0
- aicl_lang-0.1.0/aicl/env.py +26 -0
- aicl_lang-0.1.0/aicl/json_codec.py +104 -0
- aicl_lang-0.1.0/aicl/lexer.py +176 -0
- aicl_lang-0.1.0/aicl/model.py +205 -0
- aicl_lang-0.1.0/aicl/parser.py +114 -0
- aicl_lang-0.1.0/aicl/printer.py +145 -0
- aicl_lang-0.1.0/aicl/tokens.py +58 -0
- aicl_lang-0.1.0/aicl/validate.py +175 -0
- aicl_lang-0.1.0/aicl_lang.egg-info/PKG-INFO +352 -0
- aicl_lang-0.1.0/aicl_lang.egg-info/SOURCES.txt +34 -0
- aicl_lang-0.1.0/aicl_lang.egg-info/dependency_links.txt +1 -0
- aicl_lang-0.1.0/aicl_lang.egg-info/entry_points.txt +2 -0
- aicl_lang-0.1.0/aicl_lang.egg-info/requires.txt +10 -0
- aicl_lang-0.1.0/aicl_lang.egg-info/top_level.txt +1 -0
- aicl_lang-0.1.0/pyproject.toml +38 -0
- aicl_lang-0.1.0/setup.cfg +4 -0
- aicl_lang-0.1.0/tests/test_cli.py +64 -0
- aicl_lang-0.1.0/tests/test_codebook.py +107 -0
- aicl_lang-0.1.0/tests/test_coop.py +175 -0
- aicl_lang-0.1.0/tests/test_dense.py +74 -0
- aicl_lang-0.1.0/tests/test_lexer.py +65 -0
- aicl_lang-0.1.0/tests/test_readback_eval.py +70 -0
- aicl_lang-0.1.0/tests/test_roundtrip.py +94 -0
- aicl_lang-0.1.0/tests/test_rulebook.py +30 -0
- aicl_lang-0.1.0/tests/test_validate.py +112 -0
aicl_lang-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AICL contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
The specification (SPEC.md) is additionally licensed under
|
|
26
|
+
Creative Commons Attribution 4.0 International (CC BY 4.0):
|
|
27
|
+
https://creativecommons.org/licenses/by/4.0/
|
aicl_lang-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aicl-lang
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AICL: a compact, unambiguous language for agent-to-agent communication (spec + reference implementation)
|
|
5
|
+
Author: AICL contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/shotaros2/aicl
|
|
8
|
+
Project-URL: Issues, https://github.com/shotaros2/aicl/issues
|
|
9
|
+
Project-URL: Specification, https://github.com/shotaros2/aicl/blob/main/SPEC.md
|
|
10
|
+
Keywords: agents,llm,protocol,interlingua,multi-agent,speech-acts
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Provides-Extra: tokens
|
|
21
|
+
Requires-Dist: tiktoken>=0.7; extra == "tokens"
|
|
22
|
+
Provides-Extra: llm
|
|
23
|
+
Requires-Dist: anthropic>=1.0; extra == "llm"
|
|
24
|
+
Requires-Dist: google-genai>=1.0; extra == "llm"
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest; extra == "dev"
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# AICL — AI Common Language
|
|
30
|
+
|
|
31
|
+
**A common language for AI agents, the way English is for people: one tongue any agent
|
|
32
|
+
can learn, with no ambiguity.**
|
|
33
|
+
Specification + zero-dependency reference implementation. Draft v0.1.0.
|
|
34
|
+
[日本語の README はこちら](README.ja.md)
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
(ask #a.1 @a>@b (temp tokyo $t :unit C :at 2026-11-05T09:00+09:00))
|
|
38
|
+
(tell #b.1 @b>@a ^a.1 {$t 18.5C} ~0.9 :src jma)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## The problem
|
|
42
|
+
|
|
43
|
+
When two AI agents cooperate today they write each other English (or Japanese) prose:
|
|
44
|
+
|
|
45
|
+
> "Could you check whether **it** finished and, if so, roll it out to **EU**, but only if the error rate is **fine**? **Should take about 5 minutes.**"
|
|
46
|
+
|
|
47
|
+
Every bold span is a guess the receiver has to make: which object, which region id, what
|
|
48
|
+
threshold, is that an ETA or a duration, measured when. Natural language is also padded with
|
|
49
|
+
greetings, hedges and thanks that cost tokens and carry no information, and nothing about the
|
|
50
|
+
exchange is machine-checkable: no one can verify that every request got an answer.
|
|
51
|
+
|
|
52
|
+
## What AICL does
|
|
53
|
+
|
|
54
|
+
AICL is a small formal message language with four interchangeable encodings
|
|
55
|
+
(readable text, dense text for LLM-to-LLM exchange, JSON, deterministic CBOR) and one
|
|
56
|
+
canonical form that can be hashed and signed.
|
|
57
|
+
Its design rules are the whole point:
|
|
58
|
+
|
|
59
|
+
| Rule | In practice |
|
|
60
|
+
|---|---|
|
|
61
|
+
| Intent is explicit | Every message opens with a speech act: `ask tell do ok no done fail prop acc rej def clar why sub unsub end` |
|
|
62
|
+
| No pronouns | Everything is referred to by id: `#a.3`, `@bob`, `(ref #b.2)` |
|
|
63
|
+
| Numbers carry units | `18.5C`, `100USD`, `0.5%`. A bare `42` is dimensionless |
|
|
64
|
+
| Time is absolute | `2026-11-05T09:00+09:00`. "Tomorrow" does not exist |
|
|
65
|
+
| Uncertainty is numeric | `~0.8` on any form. No "probably" |
|
|
66
|
+
| Scope is structural | `(not (and a b))` cannot be misread |
|
|
67
|
+
| Unknown words are illegal | A receiver that meets a term it does not know **must** answer `clar`, never guess. Terms are introduced in-band with `def` |
|
|
68
|
+
| Natural language is quarantined | Free text only inside `(nl en "…")`, so the ambiguous part of any message is visible and measurable |
|
|
69
|
+
| Every request is closed | An `ask` ends with `tell`/`no`/`fail`; a `do` with `ok` then `done`/`fail`. The validator checks this |
|
|
70
|
+
|
|
71
|
+
The full specification is in [SPEC.md](SPEC.md) (16 pages, CC BY 4.0); the grammar in
|
|
72
|
+
[grammar/aicl.ebnf](grammar/aicl.ebnf).
|
|
73
|
+
|
|
74
|
+
### A complete exchange
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
(ask #a.1 @a>@b (deploy-status build-4821 $s :finished-at $at))
|
|
78
|
+
(tell #b.1 @b>@a ^a.1 {$s finished $at 2026-11-04T08:50Z} :src ci-api)
|
|
79
|
+
(do #a.2 @a>@b (rollout build-4821 :region eu-west-1)
|
|
80
|
+
:if (< (error-rate build-4821 :window PT10M) 0.5%))
|
|
81
|
+
(ok #b.2 @b>@a ^a.2 :eta PT5M)
|
|
82
|
+
(tell #b.3 @b>@a (error-rate build-4821 0.3% :window PT10M) :src metrics)
|
|
83
|
+
(done #b.4 @b>@a ^a.2 (rollout build-4821 :region eu-west-1 :at 2026-11-04T09:04:12Z))
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
More in [examples/](examples/): negotiation, in-band term definition and clarification,
|
|
87
|
+
subscriptions, broadcast discovery, coded failures.
|
|
88
|
+
|
|
89
|
+
### The dense form: what agents actually send
|
|
90
|
+
|
|
91
|
+
LLMs consume tokens, not bytes, so "binary" would make LLM-to-LLM traffic *more*
|
|
92
|
+
expensive (it would be base64 in the prompt). Instead, AICL has a **dense text encoding**
|
|
93
|
+
(SPEC §8): the same structure with one-letter speech acts, merged headers, one-letter
|
|
94
|
+
core keys and ISO-basic timestamps. It is bijective with the readable form, so
|
|
95
|
+
`aicl fmt` always recovers the readable version for audit and debugging.
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
(P a.1>b (meeting :a 20261106T1000+9 :dur PT30M :with [@a @b]))
|
|
99
|
+
(R b.1>a ^a.1 :w (busy @b :from 20261106T0900+9 :to 20261106T1100+9))
|
|
100
|
+
(P b.2>a (meeting :a 20261106T1400+9 :dur PT30M :with [@a @b]))
|
|
101
|
+
(C a.2>b ^b.2)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Codebooks: cheaper words without ambiguity
|
|
105
|
+
|
|
106
|
+
What a tokenizer finds cheap is accidental: `Tokyo` is one cl100k token, `tokyo` two,
|
|
107
|
+
`東京` three. A **codebook** (SPEC §8.1) is a shared table from concept ids to allowed
|
|
108
|
+
surface forms. The sender picks, per concept, the form that costs the fewest tokens on
|
|
109
|
+
the *receiver's* tokenizer; the receiver maps every form back to the concept id before
|
|
110
|
+
it reads anything. Four rules keep this exactly as unambiguous as the dense form's
|
|
111
|
+
`A` = `ask`:
|
|
112
|
+
|
|
113
|
+
1. Only concept ids are canonical: validation, hashing and `def` never see a surface form.
|
|
114
|
+
2. Each form belongs to exactly one concept (the loader rejects any table that breaks this).
|
|
115
|
+
3. A form not in the codebook is an unknown term → `clar`, never a guess. Agents must not
|
|
116
|
+
shorten or translate vocabulary on their own.
|
|
117
|
+
4. The receiver's tokenizer and codebook id are agreed in-band (`(tokenizer $t)`, `(codebook $id)`), never assumed.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
aicl codebook codebooks/imagegen.json --tokenizer cl100k_base # validate, show chosen forms
|
|
121
|
+
aicl pack msg.kd --codebook codebooks/imagegen.json --tokenizer cl100k_base
|
|
122
|
+
aicl unpack msg.kd --codebook codebooks/imagegen.json # back to concept ids
|
|
123
|
+
aicl check msg.kd --codebook codebooks/imagegen.json # concepts count as known terms
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Honest numbers: precision is not free
|
|
127
|
+
|
|
128
|
+
`bench/compare.py` compares realistic natural-language agent dialogues with the same
|
|
129
|
+
information in AICL (cl100k_base tokenizer, which GPT-4-class and many open models use).
|
|
130
|
+
All columns are tokens; "packed" uses `codebooks/bench.json`:
|
|
131
|
+
|
|
132
|
+
| case | NL | readable | ratio | dense | ratio | packed | ratio |
|
|
133
|
+
|---|---|---|---|---|---|---|---|
|
|
134
|
+
| weather | 138 | 128 | 0.93 | 98 | 0.71 | 94 | 0.68 |
|
|
135
|
+
| clarify | 188 | 239 | 1.27 | 190 | 1.01 | 186 | 0.99 |
|
|
136
|
+
| deploy | 150 | 201 | 1.34 | 164 | 1.09 | 162 | 1.08 |
|
|
137
|
+
| scheduling | 124 | 211 | 1.70 | 158 | 1.27 | 158 | 1.27 |
|
|
138
|
+
| **total** | **600** | **779** | **1.30** | **610** | **1.02** | **600** | **1.00** |
|
|
139
|
+
|
|
140
|
+
The readable form costs about 30 % more tokens than polite English, because BPE
|
|
141
|
+
vocabularies are tuned for prose. The dense form removes 22 % of that; a codebook of
|
|
142
|
+
*safe* forms (see the eval below) takes a little more and lands **at parity with natural
|
|
143
|
+
language while carrying strictly more information** (exact instants with time zones,
|
|
144
|
+
ids, thresholds, provenance) and zero ambiguity. Truncation forms would save another
|
|
145
|
+
1–2 %, but small models misread them, so the example codebook no longer uses any. In characters, every AICL form is far shorter. The scheduling case does not
|
|
146
|
+
move because its vocabulary was already one token per word; the remaining cost there is
|
|
147
|
+
the four time-zoned instants, which natural language simply leaves out.
|
|
148
|
+
|
|
149
|
+
Re-run the benchmark with your own model's tokenizer (`--tokenizer o200k_base`, or any
|
|
150
|
+
`tiktoken` encoding) before drawing conclusions for it.
|
|
151
|
+
|
|
152
|
+
### Does the model still read it correctly?
|
|
153
|
+
|
|
154
|
+
The library decodes every encoding perfectly; the open question is whether a *language
|
|
155
|
+
model* does, especially for packed messages that mix scripts. `evals/readback.py` asks a
|
|
156
|
+
model to write the canonical form of every example message in each encoding, parses and
|
|
157
|
+
canonicalises the answer, and reports accuracy and tokens per encoding:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
python evals/readback.py --dry-run # 69 messages x 4 encodings, no API calls
|
|
161
|
+
python evals/readback.py --provider anthropic --model claude-opus-5-5 --out evals/results/opus-5-5.json
|
|
162
|
+
python evals/readback.py --provider gemini --model gemini-3.8-flash --out evals/results/gemini-3.8-flash.json
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Providers: `anthropic` (`pip install anthropic`, `ANTHROPIC_API_KEY`) and `gemini`
|
|
166
|
+
(`pip install google-genai`, `GEMINI_API_KEY`). Any other model needs one function of
|
|
167
|
+
the form `ask(system, user) -> str` added to `PROVIDERS`.
|
|
168
|
+
|
|
169
|
+
A token saving that lowers read-back accuracy is a loss; adopt a codebook for a model only
|
|
170
|
+
after this eval passes for it. Results so far (`evals/results/`, first 10 messages,
|
|
171
|
+
`gemini-3.5-flash-lite`, the smallest model available to us):
|
|
172
|
+
|
|
173
|
+
| encoding | accuracy | what failed |
|
|
174
|
+
|---|---|---|
|
|
175
|
+
| readable | 90 % | one term "corrected" to a codebook form |
|
|
176
|
+
| dense | **100 %** | — |
|
|
177
|
+
| packed | 60 % → 80 % → 90 % | English truncations (`deploy`, `roll`, `err`) left unexpanded; last failure is one key code (`:u`) |
|
|
178
|
+
| packed-chars | 80 % → 90 % → 90 % | same |
|
|
179
|
+
|
|
180
|
+
The first arrow is the effect of presenting the codebook form→concept and adding worked
|
|
181
|
+
examples to the eval prompt; the second is removing truncation forms from the codebook.
|
|
182
|
+
With forms that look like forms, the only remaining miss is a dense key code, and the
|
|
183
|
+
vocabulary errors are gone. Two conclusions: **the dense form is safe even for a small
|
|
184
|
+
model**, and **codebook forms must look like forms** (CamelCase, all-caps, non-Latin):
|
|
185
|
+
truncations that read as real words are the failure mode, so the example codebooks no
|
|
186
|
+
longer contain any and the loader warns about them. Results for larger models are welcome.
|
|
187
|
+
|
|
188
|
+
## Install and use
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
pip install -e . # or: pip install aicl-lang (once published)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
aicl fmt examples/02_deploy.aicl # canonical single-line form (also decodes dense input)
|
|
196
|
+
aicl dense examples/02_deploy.aicl # dense text encoding for LLM-to-LLM exchange
|
|
197
|
+
aicl pretty examples/02_deploy.aicl # readable layout
|
|
198
|
+
aicl json examples/02_deploy.aicl # JSON encoding
|
|
199
|
+
aicl cbor examples/01_weather.aicl -o m.cbor
|
|
200
|
+
aicl hash examples/02_deploy.aicl # sha256 of canonical form, per message
|
|
201
|
+
aicl check examples/02_deploy.aicl --known deploy-status --known rollout --known error-rate
|
|
202
|
+
aicl stats examples/05_subscription.aicl # size, tokens, nl ratio
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
import aicl
|
|
207
|
+
|
|
208
|
+
msgs = aicl.parse_messages(open("examples/02_deploy.aicl").read())
|
|
209
|
+
for issue in aicl.validate_conversation(msgs, known_terms=["deploy-status", "rollout", "error-rate"]):
|
|
210
|
+
print(issue) # protocol violations, open requests, unresolved terms
|
|
211
|
+
|
|
212
|
+
m = msgs[1]
|
|
213
|
+
print(m.act, m.sender, m.receiver, m.reply) # tell b a a.1
|
|
214
|
+
print(aicl.to_text(m.to_form())) # canonical text
|
|
215
|
+
print(aicl.to_dense(m.to_form())) # dense text
|
|
216
|
+
print(aicl.to_json_text(m.to_form())) # canonical JSON
|
|
217
|
+
print(aicl.digest(m.to_form())) # sha256
|
|
218
|
+
|
|
219
|
+
from aicl.build import msg, form, q
|
|
220
|
+
reply = msg("tell", "b.9", "b", "a", aicl.KMap([(aicl.Var("t"), q(18.5, "C"))]), reply="a.1", conf=0.9)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Cooperation: specialists working together
|
|
224
|
+
|
|
225
|
+
AIs have different strengths. The cooperation layer (`aicl/coop.py`,
|
|
226
|
+
[schemas/cooperation.md](schemas/cooperation.md)) lets an image agent, a video agent and a
|
|
227
|
+
code agent work on one goal, speaking only AICL:
|
|
228
|
+
|
|
229
|
+
- **Specialists** announce `(coop:capability image-gen :agent @img)`, accept
|
|
230
|
+
`(coop:task …)` with `ok`, and return `(coop:artifact …)` with `done`.
|
|
231
|
+
- A **hub** keeps the registry, turns the requester's goal into a `(coop:plan …)`, delegates
|
|
232
|
+
tasks in dependency order and passes each artifact to the next task in full, never as
|
|
233
|
+
"the previous result".
|
|
234
|
+
- The **bus** validates every message; a specialist's `fail` reaches the requester as `fail`
|
|
235
|
+
with `:why (ref #…)`, never as a silent retry.
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
(do #user.1 @user>@hub (coop:goal (nl ja "東京の夜景の10秒動画を作って、それを埋め込んだWebページを作って")))
|
|
239
|
+
(tell #hub.2 @hub>@user (coop:plan [(coop:task t1 image-gen …) (coop:task t2 video-gen :in {keyframe (coop:from t1) …}) (coop:task t3 code-gen …)]))
|
|
240
|
+
(do #hub.3 @hub>@img (coop:task t1 image-gen :in {prompt "Tokyo skyline at night" width 1920px height 1080px}))
|
|
241
|
+
(done #img.3 @img>@hub ^hub.3 (coop:artifact img-974186 :type image :task t1 :uri "file://out/img-974186.png"))
|
|
242
|
+
(do #hub.4 @hub>@vid (coop:task t2 video-gen :in {keyframe (coop:artifact img-974186 …) duration 10s}))
|
|
243
|
+
…
|
|
244
|
+
(done #hub.6 @hub>@user ^user.1 [(coop:artifact img-974186 …) (coop:artifact vid-… :type video …) (coop:artifact page-1 :type code :content "<!doctype html>…")])
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
`python examples/cooperation_demo.py` runs this offline with stub specialists: 16 messages,
|
|
248
|
+
0 protocol errors, natural language only inside the user's goal (nl ratio 2 %). Swap the
|
|
249
|
+
stub functions for real APIs, or use `LLMAgent` for a model-backed specialist and
|
|
250
|
+
`LLMPlanner` for a model-backed hub, and nothing else changes.
|
|
251
|
+
|
|
252
|
+
`python examples/cooperation_gemini.py` does exactly that with Gemini in three roles
|
|
253
|
+
(`GEMINI_API_KEY` required): the hub's planner writes the plan in AICL, the image
|
|
254
|
+
specialist calls a Gemini image model and returns the PNG as an artifact, and the code
|
|
255
|
+
specialist *is* Gemini speaking dense AICL, answering the task with `K` and `Z` messages
|
|
256
|
+
that the bus validates before accepting. Output lands in `out/` (transcript, image, page).
|
|
257
|
+
On the free tier Gemini's image models are not available (a consumer Gemini subscription
|
|
258
|
+
does not change API quotas), so by default the text model draws the image as SVG;
|
|
259
|
+
`--image-model gemini-nano-banana-2.1` uses a real image model once API billing is on. Live runs with `gemini-3.5-flash-lite` as planner
|
|
260
|
+
and code agent: the plan, two dependent tasks and both artifacts reach the requester in
|
|
261
|
+
12 messages with 0 protocol errors. Getting there taught three things, all now in the code:
|
|
262
|
+
the harness, not the model, owns message ids (it tells the model its next id and reply
|
|
263
|
+
header as an AICL comment, and renumbers if needed); a malformed reply gets one correction
|
|
264
|
+
turn with the validator's verdict before it becomes `fail :code parse`; and two redundant-sigil
|
|
265
|
+
slips a small model makes (`a.1>@b`, `^#a.1`) are accepted on input because they cannot
|
|
266
|
+
change meaning, while anything ambiguous is still rejected.
|
|
267
|
+
|
|
268
|
+
## Make an LLM speak AICL
|
|
269
|
+
|
|
270
|
+
[prompts/system_prompt.md](prompts/system_prompt.md) is a ~700-token system prompt that
|
|
271
|
+
teaches any instruction-following model the readable language;
|
|
272
|
+
[prompts/system_prompt_dense.md](prompts/system_prompt_dense.md) teaches the dense form,
|
|
273
|
+
which is what two LLM agents should use with each other. `examples/llm_dialogue.py` runs two
|
|
274
|
+
Claude instances negotiating a meeting in AICL, with every message parsed and validated
|
|
275
|
+
at the boundary before it is delivered:
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
pip install anthropic
|
|
279
|
+
python examples/llm_dialogue.py
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
`examples/two_agents_demo.py` does the same with rule-based agents and no network.
|
|
283
|
+
|
|
284
|
+
### Hand the folder to your own agent
|
|
285
|
+
|
|
286
|
+
The repository is self-describing for agents that read a project folder:
|
|
287
|
+
|
|
288
|
+
- `AGENTS.md` (Codex, Cursor and most general agents) and `CLAUDE.md` (Claude Code)
|
|
289
|
+
tell the agent to load the system prompt and validate every message with `aicl check`.
|
|
290
|
+
- `SKILL.md` makes the folder an [Agent Skill](https://github.com/anthropics/skills):
|
|
291
|
+
copy it to `.claude/skills/aicl/` (or your framework's skills directory) and the
|
|
292
|
+
agent loads AICL only when it talks to another agent.
|
|
293
|
+
|
|
294
|
+
Two agents that have both read this folder can talk to each other in AICL with no
|
|
295
|
+
further setup; the validator is the referee.
|
|
296
|
+
|
|
297
|
+
If you only want to hand over the language (no code), give the agent the
|
|
298
|
+
[rulebook/](rulebook/) folder: both language references, the spec, the example codebooks
|
|
299
|
+
and the worked conversations, with a bilingual index saying which file is for what. It is
|
|
300
|
+
generated by `python tools/build_rulebook.py` and checked by the test suite, so it never
|
|
301
|
+
drifts from the sources.
|
|
302
|
+
|
|
303
|
+
## Repository layout
|
|
304
|
+
|
|
305
|
+
```
|
|
306
|
+
SPEC.md the language (normative)
|
|
307
|
+
grammar/aicl.ebnf text encoding grammar
|
|
308
|
+
aicl/ reference implementation (Python ≥ 3.11, no dependencies)
|
|
309
|
+
lexer.py parser.py text → terms
|
|
310
|
+
printer.py canonical + pretty text, sha256 digest
|
|
311
|
+
dense.py dense text encoding (tokenizer-tuned, bijective with canonical)
|
|
312
|
+
codebook.py tokenizer-aware codebooks: pack / unpack with the ambiguity rules
|
|
313
|
+
coop.py cooperation layer: bus, specialists, hub, planners
|
|
314
|
+
schemas/ published vocabularies (cooperation)
|
|
315
|
+
codebooks/ example codebooks (bench, imagegen)
|
|
316
|
+
json_codec.py JSON encoding
|
|
317
|
+
cbor_codec.py deterministic CBOR (RFC 8949 §4.2)
|
|
318
|
+
validate.py message + conversation validator, nl ratio
|
|
319
|
+
cli.py `aicl` command
|
|
320
|
+
examples/ worked conversations + demos
|
|
321
|
+
prompts/ system prompts for LLM agents (readable and dense)
|
|
322
|
+
rulebook/ generated hand-off folder: language references, spec, codebooks, examples
|
|
323
|
+
tools/ build_rulebook.py
|
|
324
|
+
bench/ NL vs AICL comparison
|
|
325
|
+
evals/ LLM read-back accuracy evaluation
|
|
326
|
+
tests/ unittest suite (also the conformance tests)
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Relation to prior work
|
|
330
|
+
|
|
331
|
+
- **KQML / FIPA-ACL** (1990s agent communication languages) introduced speech-act
|
|
332
|
+
performatives; AICL keeps that idea and adds what LLM agents need: quarantined natural
|
|
333
|
+
language, numeric confidence, in-band term definition and a canonical, hashable form.
|
|
334
|
+
- **JSON-RPC, MCP, A2A** are transports and tool-call envelopes. They say nothing about the
|
|
335
|
+
*content* agents exchange; a AICL message can travel inside any of them (use the JSON encoding).
|
|
336
|
+
- **Lojban, Ithkuil** are unambiguous languages for humans. AICL is for machines and is
|
|
337
|
+
deliberately tiny.
|
|
338
|
+
|
|
339
|
+
## Roadmap
|
|
340
|
+
|
|
341
|
+
- v0.2: standard published codebooks per domain, shared by id; typed `def` signatures;
|
|
342
|
+
standard schemas for scheduling, data query and tool invocation.
|
|
343
|
+
- Ports: the implementation is ~1700 lines including docstrings and meant to be re-implemented in an afternoon.
|
|
344
|
+
Conformance criteria are in SPEC §12; open an issue to be listed here.
|
|
345
|
+
- Identity and signatures (`@agent` → public key).
|
|
346
|
+
|
|
347
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for how language changes are proposed.
|
|
348
|
+
|
|
349
|
+
## License
|
|
350
|
+
|
|
351
|
+
Code: MIT. Specification: CC BY 4.0. AICL stands for *AI Common Language*; the project was
|
|
352
|
+
briefly called Koine before 0.1.0.
|