inter-agent-core 0.2.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.
Files changed (91) hide show
  1. inter_agent_core-0.2.0/ARCHITECTURE.md +32 -0
  2. inter_agent_core-0.2.0/CHANGELOG.md +13 -0
  3. inter_agent_core-0.2.0/LICENSE.md +21 -0
  4. inter_agent_core-0.2.0/MANIFEST.in +8 -0
  5. inter_agent_core-0.2.0/PKG-INFO +85 -0
  6. inter_agent_core-0.2.0/README.md +62 -0
  7. inter_agent_core-0.2.0/SECURITY.md +26 -0
  8. inter_agent_core-0.2.0/docs/SECURITY_BASELINE.md +10 -0
  9. inter_agent_core-0.2.0/docs/THREAT_MODEL.md +18 -0
  10. inter_agent_core-0.2.0/pyproject.toml +95 -0
  11. inter_agent_core-0.2.0/setup.cfg +4 -0
  12. inter_agent_core-0.2.0/spec/asyncapi.yaml +225 -0
  13. inter_agent_core-0.2.0/spec/error-codes.md +28 -0
  14. inter_agent_core-0.2.0/spec/examples/auth_challenge.json +6 -0
  15. inter_agent_core-0.2.0/spec/examples/auth_response.json +4 -0
  16. inter_agent_core-0.2.0/spec/examples/broadcast.json +4 -0
  17. inter_agent_core-0.2.0/spec/examples/bye.json +3 -0
  18. inter_agent_core-0.2.0/spec/examples/channels.json +3 -0
  19. inter_agent_core-0.2.0/spec/examples/channels_ok.json +9 -0
  20. inter_agent_core-0.2.0/spec/examples/custom.unknown-pass-through.json +9 -0
  21. inter_agent_core-0.2.0/spec/examples/error.auth-failed.json +5 -0
  22. inter_agent_core-0.2.0/spec/examples/hello.agent-with-label.json +14 -0
  23. inter_agent_core-0.2.0/spec/examples/hello.agent.json +13 -0
  24. inter_agent_core-0.2.0/spec/examples/kick.json +4 -0
  25. inter_agent_core-0.2.0/spec/examples/kick_ok.json +5 -0
  26. inter_agent_core-0.2.0/spec/examples/list.json +3 -0
  27. inter_agent_core-0.2.0/spec/examples/list_ok.json +10 -0
  28. inter_agent_core-0.2.0/spec/examples/msg.custom.json +13 -0
  29. inter_agent_core-0.2.0/spec/examples/msg.text.json +9 -0
  30. inter_agent_core-0.2.0/spec/examples/ping.json +3 -0
  31. inter_agent_core-0.2.0/spec/examples/pong.json +3 -0
  32. inter_agent_core-0.2.0/spec/examples/publish.json +5 -0
  33. inter_agent_core-0.2.0/spec/examples/send.direct.json +5 -0
  34. inter_agent_core-0.2.0/spec/examples/shutdown.json +3 -0
  35. inter_agent_core-0.2.0/spec/examples/shutdown_ok.json +3 -0
  36. inter_agent_core-0.2.0/spec/examples/subscribe.json +4 -0
  37. inter_agent_core-0.2.0/spec/examples/subscribe_ok.json +4 -0
  38. inter_agent_core-0.2.0/spec/examples/unsubscribe.json +4 -0
  39. inter_agent_core-0.2.0/spec/examples/unsubscribe_ok.json +4 -0
  40. inter_agent_core-0.2.0/spec/examples/welcome.json +10 -0
  41. inter_agent_core-0.2.0/spec/schemas/auth_challenge.json +13 -0
  42. inter_agent_core-0.2.0/spec/schemas/auth_response.json +11 -0
  43. inter_agent_core-0.2.0/spec/schemas/broadcast.json +18 -0
  44. inter_agent_core-0.2.0/spec/schemas/bye.json +10 -0
  45. inter_agent_core-0.2.0/spec/schemas/channels.json +10 -0
  46. inter_agent_core-0.2.0/spec/schemas/channels_ok.json +26 -0
  47. inter_agent_core-0.2.0/spec/schemas/custom.json +22 -0
  48. inter_agent_core-0.2.0/spec/schemas/error.json +37 -0
  49. inter_agent_core-0.2.0/spec/schemas/hello.json +59 -0
  50. inter_agent_core-0.2.0/spec/schemas/kick.json +13 -0
  51. inter_agent_core-0.2.0/spec/schemas/kick_ok.json +12 -0
  52. inter_agent_core-0.2.0/spec/schemas/list.json +10 -0
  53. inter_agent_core-0.2.0/spec/schemas/list_ok.json +24 -0
  54. inter_agent_core-0.2.0/spec/schemas/msg.json +29 -0
  55. inter_agent_core-0.2.0/spec/schemas/ping.json +10 -0
  56. inter_agent_core-0.2.0/spec/schemas/pong.json +10 -0
  57. inter_agent_core-0.2.0/spec/schemas/publish.json +23 -0
  58. inter_agent_core-0.2.0/spec/schemas/send.json +22 -0
  59. inter_agent_core-0.2.0/spec/schemas/shutdown.json +10 -0
  60. inter_agent_core-0.2.0/spec/schemas/shutdown_ok.json +10 -0
  61. inter_agent_core-0.2.0/spec/schemas/subscribe.json +15 -0
  62. inter_agent_core-0.2.0/spec/schemas/subscribe_ok.json +11 -0
  63. inter_agent_core-0.2.0/spec/schemas/unsubscribe.json +15 -0
  64. inter_agent_core-0.2.0/spec/schemas/unsubscribe_ok.json +11 -0
  65. inter_agent_core-0.2.0/spec/schemas/welcome.json +36 -0
  66. inter_agent_core-0.2.0/src/inter_agent/__init__.py +0 -0
  67. inter_agent_core-0.2.0/src/inter_agent/core/__init__.py +1 -0
  68. inter_agent_core-0.2.0/src/inter_agent/core/adapter_control.py +350 -0
  69. inter_agent_core-0.2.0/src/inter_agent/core/auth.py +279 -0
  70. inter_agent_core-0.2.0/src/inter_agent/core/channels.py +131 -0
  71. inter_agent_core-0.2.0/src/inter_agent/core/client.py +345 -0
  72. inter_agent_core-0.2.0/src/inter_agent/core/config.py +325 -0
  73. inter_agent_core-0.2.0/src/inter_agent/core/errors.py +31 -0
  74. inter_agent_core-0.2.0/src/inter_agent/core/kick.py +111 -0
  75. inter_agent_core-0.2.0/src/inter_agent/core/list.py +127 -0
  76. inter_agent_core-0.2.0/src/inter_agent/core/publish.py +146 -0
  77. inter_agent_core-0.2.0/src/inter_agent/core/router.py +8 -0
  78. inter_agent_core-0.2.0/src/inter_agent/core/send.py +265 -0
  79. inter_agent_core-0.2.0/src/inter_agent/core/server.py +765 -0
  80. inter_agent_core-0.2.0/src/inter_agent/core/shared.py +182 -0
  81. inter_agent_core-0.2.0/src/inter_agent/core/shutdown.py +92 -0
  82. inter_agent_core-0.2.0/src/inter_agent/core/status.py +291 -0
  83. inter_agent_core-0.2.0/src/inter_agent/core/tls.py +141 -0
  84. inter_agent_core-0.2.0/src/inter_agent/core/transport.py +37 -0
  85. inter_agent_core-0.2.0/src/inter_agent/py.typed +0 -0
  86. inter_agent_core-0.2.0/src/inter_agent_core.egg-info/PKG-INFO +85 -0
  87. inter_agent_core-0.2.0/src/inter_agent_core.egg-info/SOURCES.txt +89 -0
  88. inter_agent_core-0.2.0/src/inter_agent_core.egg-info/dependency_links.txt +1 -0
  89. inter_agent_core-0.2.0/src/inter_agent_core.egg-info/entry_points.txt +10 -0
  90. inter_agent_core-0.2.0/src/inter_agent_core.egg-info/requires.txt +2 -0
  91. inter_agent_core-0.2.0/src/inter_agent_core.egg-info/top_level.txt +1 -0
@@ -0,0 +1,32 @@
1
+ # Architecture
2
+
3
+ `inter-agent-core` is a local WebSocket message bus for cooperating sessions.
4
+
5
+ ## Runtime
6
+
7
+ The `inter_agent.core` package owns transport, TLS, authentication, endpoint and shared-secret resolution, session identity, routing, resource limits, server lifecycle, and generic command APIs. The default endpoint is `127.0.0.1:16837`.
8
+
9
+ The server authenticates every connection with an HMAC-SHA-256 challenge-response using a shared secret. A connection becomes an agent session only after authentication. Direct messages route by name, broadcasts route to other agent sessions, and channels are in-memory pub/sub groups scoped to one server.
10
+
11
+ ## Protocol
12
+
13
+ The protocol contract lives in [spec/](spec/):
14
+
15
+ - `asyncapi.yaml` describes the transport contract.
16
+ - `schemas/` contains operation schemas.
17
+ - `examples/` contains canonical payloads.
18
+ - `error-codes.md` defines machine-readable failures.
19
+
20
+ `core.version` is a protocol capability, not the package version.
21
+
22
+ ## Extension boundary
23
+
24
+ Host extensions own host interaction, listener lifetime, rendering, and host-local state. Python extensions use the typed core command and listener APIs. The narrow `inter_agent.core.adapter_control` module provides a same-user local control socket for a host listener's subscribe/unsubscribe operations; it does not carry the bus secret.
25
+
26
+ Core does not ship host plugins, host adapters, marketplace metadata, or host-specific setup.
27
+
28
+ ## Lifecycle and transport
29
+
30
+ Manual servers remain running until authenticated shutdown unless `--idle-timeout` is supplied. Loopback endpoints default to `ws://`; non-loopback endpoints default to `wss://` unless TLS is explicitly disabled. Clients must not downgrade a failed TLS connection to plaintext.
31
+
32
+ Configuration resolves from explicit command options, environment, the inter-agent config file, then defaults. Secret resolution prefers `INTER_AGENT_SECRET`, then config `secret`, then a generated state-file token. Details and security assumptions are in [SECURITY.md](SECURITY.md).
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ All notable changes to `inter-agent-core` are recorded here.
4
+
5
+ ## Versioning policy
6
+
7
+ The Python distribution version in `pyproject.toml` is the source of truth for core artifacts. The protocol capability `core.version` is a compatibility value and is versioned independently from the Python distribution.
8
+
9
+ ## 0.2.0
10
+
11
+ Clean standalone baseline for the host-neutral inter-agent runtime. It includes the local authenticated server, generic command-line clients, protocol contract, TLS/authentication/state behavior, and the typed `inter_agent.core.adapter_control` extension-support API.
12
+
13
+ No protocol behavior changes are introduced by this repository extraction.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 arcanemachine
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.
@@ -0,0 +1,8 @@
1
+ include README.md
2
+ include ARCHITECTURE.md
3
+ include SECURITY.md
4
+ include CHANGELOG.md
5
+ include LICENSE.md
6
+ recursive-include docs *.md
7
+ recursive-include spec *.yaml *.json *.md
8
+ prune tests
@@ -0,0 +1,85 @@
1
+ Metadata-Version: 2.4
2
+ Name: inter-agent-core
3
+ Version: 0.2.0
4
+ Summary: Local authenticated message bus runtime and command-line tools
5
+ Author-email: Nicholas Moen <arcanemachine@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/arcanemachine/inter-agent-core
8
+ Project-URL: Repository, https://github.com/arcanemachine/inter-agent-core
9
+ Project-URL: Issues, https://github.com/arcanemachine/inter-agent-core/issues
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Communications
17
+ Requires-Python: >=3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE.md
20
+ Requires-Dist: cryptography==46.0.3
21
+ Requires-Dist: websockets==16.0
22
+ Dynamic: license-file
23
+
24
+ # inter-agent-core
25
+
26
+ This project provides a way for agentic applications (e.g. coding harnesses) to talk to each other.
27
+
28
+ `inter-agent-core` is a host-neutral Python runtime for a local, authenticated message bus. It provides the server, generic clients and commands, protocol contract, shared endpoint/secret state, routing, TLS, and lifecycle controls used by host extensions.
29
+
30
+ Pi and Claude Code integrations are separate repositories:
31
+
32
+ - [inter-agent-pi](https://github.com/arcanemachine/inter-agent-pi)
33
+ - [inter-agent-claude-code](https://github.com/arcanemachine/inter-agent-claude-code)
34
+
35
+ ## Source checkout quick start
36
+
37
+ ```bash
38
+ git clone https://github.com/arcanemachine/inter-agent-core.git
39
+ cd inter-agent-core
40
+ uv sync --locked
41
+ uv run inter-agent-server
42
+ ```
43
+
44
+ In another terminal, inspect the local bus:
45
+
46
+ ```bash
47
+ uv run inter-agent-status
48
+ uv run inter-agent-list
49
+ ```
50
+
51
+ The default endpoint is `127.0.0.1:16837`. Local clients share endpoint and secret discovery through the same configuration/state rules. Use `inter-agent-shutdown` only when you intend to stop the shared server; it affects every connected client.
52
+
53
+ ## Generic commands
54
+
55
+ ```text
56
+ inter-agent-server
57
+ inter-agent-connect
58
+ inter-agent-send
59
+ inter-agent-list
60
+ inter-agent-status
61
+ inter-agent-shutdown
62
+ inter-agent-kick
63
+ inter-agent-publish
64
+ inter-agent-channels
65
+ ```
66
+
67
+ Use `--help` on a command for its options. Host-specific setup and session UX belong to the extension repositories.
68
+
69
+ ## Security
70
+
71
+ The default design is one user on one machine. Connections authenticate with a shared secret. Loopback connections default to plaintext WebSockets; non-loopback connections default to TLS. TLS encrypts transport but does not protect against hostile code running as the same operating-system user.
72
+
73
+ See [SECURITY.md](SECURITY.md) for the full model and [ARCHITECTURE.md](ARCHITECTURE.md) for protocol/runtime details.
74
+
75
+ ## Development
76
+
77
+ ```bash
78
+ ./run-checks.sh
79
+ ```
80
+
81
+ Protocol schemas, examples, and canonical error codes are in [spec/](spec/).
82
+
83
+ ## License
84
+
85
+ MIT
@@ -0,0 +1,62 @@
1
+ # inter-agent-core
2
+
3
+ This project provides a way for agentic applications (e.g. coding harnesses) to talk to each other.
4
+
5
+ `inter-agent-core` is a host-neutral Python runtime for a local, authenticated message bus. It provides the server, generic clients and commands, protocol contract, shared endpoint/secret state, routing, TLS, and lifecycle controls used by host extensions.
6
+
7
+ Pi and Claude Code integrations are separate repositories:
8
+
9
+ - [inter-agent-pi](https://github.com/arcanemachine/inter-agent-pi)
10
+ - [inter-agent-claude-code](https://github.com/arcanemachine/inter-agent-claude-code)
11
+
12
+ ## Source checkout quick start
13
+
14
+ ```bash
15
+ git clone https://github.com/arcanemachine/inter-agent-core.git
16
+ cd inter-agent-core
17
+ uv sync --locked
18
+ uv run inter-agent-server
19
+ ```
20
+
21
+ In another terminal, inspect the local bus:
22
+
23
+ ```bash
24
+ uv run inter-agent-status
25
+ uv run inter-agent-list
26
+ ```
27
+
28
+ The default endpoint is `127.0.0.1:16837`. Local clients share endpoint and secret discovery through the same configuration/state rules. Use `inter-agent-shutdown` only when you intend to stop the shared server; it affects every connected client.
29
+
30
+ ## Generic commands
31
+
32
+ ```text
33
+ inter-agent-server
34
+ inter-agent-connect
35
+ inter-agent-send
36
+ inter-agent-list
37
+ inter-agent-status
38
+ inter-agent-shutdown
39
+ inter-agent-kick
40
+ inter-agent-publish
41
+ inter-agent-channels
42
+ ```
43
+
44
+ Use `--help` on a command for its options. Host-specific setup and session UX belong to the extension repositories.
45
+
46
+ ## Security
47
+
48
+ The default design is one user on one machine. Connections authenticate with a shared secret. Loopback connections default to plaintext WebSockets; non-loopback connections default to TLS. TLS encrypts transport but does not protect against hostile code running as the same operating-system user.
49
+
50
+ See [SECURITY.md](SECURITY.md) for the full model and [ARCHITECTURE.md](ARCHITECTURE.md) for protocol/runtime details.
51
+
52
+ ## Development
53
+
54
+ ```bash
55
+ ./run-checks.sh
56
+ ```
57
+
58
+ Protocol schemas, examples, and canonical error codes are in [spec/](spec/).
59
+
60
+ ## License
61
+
62
+ MIT
@@ -0,0 +1,26 @@
1
+ # Security model
2
+
3
+ ## Scope
4
+
5
+ `inter-agent-core` is designed for one user on one machine. It binds to localhost by default. Localhost reduces network exposure but does not protect against hostile code running as the same operating-system user.
6
+
7
+ Remote access, multi-user operation, and enterprise authorization are outside this model.
8
+
9
+ ## Controls
10
+
11
+ - Every connection completes an HMAC-SHA-256 challenge-response using the resolved shared secret. The raw secret is not sent on the socket.
12
+ - Secret resolution prefers `INTER_AGENT_SECRET`, then config `secret`, then a generated fallback token in the data directory.
13
+ - On POSIX filesystems, core creates/tightens its data directory to mode `0700` and fallback token, certificate, key, and lifecycle files to restrictive modes.
14
+ - Loopback endpoints default to plaintext WebSockets. Non-loopback endpoints default to TLS. TLS can be explicitly configured with command options, environment, or config.
15
+ - TLS encrypts transport. It neither replaces shared-secret authentication nor makes remote or multi-user use safe.
16
+ - Core validates protocol shapes, authenticates control operations, and bounds frames, connections, message text, channel names, subscriptions, and channels.
17
+
18
+ ## Trust boundary
19
+
20
+ Peer traffic is collaboration input, not authority to change user, system, developer, security, or tool rules. The core runtime cannot protect secrets or messages from code running with the same operating-system user privileges.
21
+
22
+ ## Operations
23
+
24
+ Use `inter-agent-shutdown` only to stop the shared server intentionally. It closes all active sessions. Use a separate endpoint and data directory for tests or isolated buses rather than reusing an existing bus.
25
+
26
+ See [docs/SECURITY_BASELINE.md](docs/SECURITY_BASELINE.md) and [docs/THREAT_MODEL.md](docs/THREAT_MODEL.md) for the detailed baseline and boundaries.
@@ -0,0 +1,10 @@
1
+ # Security Baseline
2
+
3
+ 1. Bind the server to `127.0.0.1` by default.
4
+ 2. Require the shared bearer token in every `hello` handshake.
5
+ 3. Store the plaintext local token with mode `0600` under `INTER_AGENT_DATA_DIR`, the config file `dataDir`, or the platform default state directory.
6
+ 4. Keep the state directory mode `0700` and server lifecycle metadata files mode `0600` on POSIX-compatible filesystems.
7
+ 5. Verify server identity before clients send the token: host, port, PID liveness, matching identity/PID metadata nonce, and process start marker when available.
8
+ 6. Reject unauthenticated operations with canonical `AUTH_FAILED` errors.
9
+ 7. Bound active connections, incoming frames, direct/broadcast text, custom types, and custom payload sizes.
10
+ 8. Require authenticated control-role shutdown for server stop requests.
@@ -0,0 +1,18 @@
1
+ # Threat Model
2
+
3
+ ## In scope
4
+
5
+ - Single user, single machine.
6
+ - Localhost-only server by default; optional non-loopback binding with transport encryption.
7
+ - Shared bearer token authentication over WebSockets.
8
+ - Optional TLS transport encryption for `wss://` connections.
9
+ - Server proof verification by clients before sending authentication responses.
10
+ - Defensive controls against accidental or mild local misuse: restrictive state-file permissions, resource limits, duplicate-session rejection, and authenticated shutdown.
11
+
12
+ ## Out of scope
13
+
14
+ - Protection against malicious code already running as the same OS user.
15
+ - Cross-machine trust, PKI lifecycle, mTLS, or remote transport hardening beyond transport encryption.
16
+ - Multi-tenant permission isolation or enterprise RBAC.
17
+ - Protection from a local process that can read or modify the user's inter-agent state directory contents.
18
+ - Treating TLS as sufficient for safe remote or multi-user operation.
@@ -0,0 +1,95 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "inter-agent-core"
7
+ version = "0.2.0"
8
+ description = "Local authenticated message bus runtime and command-line tools"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "Nicholas Moen", email = "arcanemachine@gmail.com" },
14
+ ]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Developers",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Topic :: Communications",
23
+ ]
24
+ dependencies = [
25
+ "cryptography==46.0.3",
26
+ "websockets==16.0",
27
+ ]
28
+
29
+ [project.urls]
30
+ Homepage = "https://github.com/arcanemachine/inter-agent-core"
31
+ Repository = "https://github.com/arcanemachine/inter-agent-core"
32
+ Issues = "https://github.com/arcanemachine/inter-agent-core/issues"
33
+
34
+ [project.scripts]
35
+ inter-agent-server = "inter_agent.core.server:main"
36
+ inter-agent-connect = "inter_agent.core.client:main"
37
+ inter-agent-send = "inter_agent.core.send:main"
38
+ inter-agent-list = "inter_agent.core.list:main"
39
+ inter-agent-status = "inter_agent.core.status:main"
40
+ inter-agent-shutdown = "inter_agent.core.shutdown:main"
41
+ inter-agent-kick = "inter_agent.core.kick:main"
42
+ inter-agent-publish = "inter_agent.core.publish:main"
43
+ inter-agent-channels = "inter_agent.core.channels:main"
44
+
45
+ [dependency-groups]
46
+ dev = [
47
+ "pytest==9.0.3",
48
+ "pytest-asyncio==1.3.0",
49
+ "ruff==0.15.12",
50
+ "black==26.3.1",
51
+ "mypy==1.20.2",
52
+ "jsonschema==4.26.0",
53
+ "pyyaml==6.0.3",
54
+ ]
55
+
56
+ [tool.setuptools]
57
+ include-package-data = true
58
+
59
+ [tool.setuptools.packages.find]
60
+ where = ["src"]
61
+
62
+ [tool.setuptools.package-data]
63
+ inter_agent = ["py.typed"]
64
+
65
+ [tool.setuptools.data-files]
66
+ "share/inter-agent/spec" = ["spec/asyncapi.yaml", "spec/error-codes.md"]
67
+ "share/inter-agent/spec/schemas" = ["spec/schemas/*.json"]
68
+ "share/inter-agent/spec/examples" = ["spec/examples/*.json"]
69
+
70
+ [tool.pytest.ini_options]
71
+ asyncio_mode = "auto"
72
+
73
+ [tool.black]
74
+ line-length = 100
75
+ target-version = ["py312"]
76
+
77
+ [tool.ruff]
78
+ line-length = 100
79
+ target-version = "py312"
80
+
81
+ [tool.ruff.lint]
82
+ select = ["E", "F", "I", "B", "UP"]
83
+
84
+ [tool.mypy]
85
+ python_version = "3.12"
86
+ strict = true
87
+ ignore_missing_imports = true
88
+
89
+ [[tool.mypy.overrides]]
90
+ module = ["yaml"]
91
+ ignore_missing_imports = true
92
+
93
+ [[tool.mypy.overrides]]
94
+ module = ["tests.*"]
95
+ disallow_untyped_defs = false
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,225 @@
1
+ asyncapi: 2.6.0
2
+ id: urn:inter-agent:protocol
3
+ info:
4
+ title: inter-agent protocol
5
+ version: 0.1.0
6
+ description: >
7
+ Minimal universal-friendly protocol for an inter-agent bus. Clients connect
8
+ over WebSocket (`ws://` or `wss://`) and start with `hello`, complete an
9
+ HMAC-SHA-256 challenge-response using a shared secret, then receive
10
+ `welcome`. Loopback hosts default to plaintext `ws://` unless TLS is
11
+ explicitly enabled; non-loopback hosts default to TLS `wss://` unless TLS
12
+ is explicitly disabled. Handshake capabilities are JSON objects: clients
13
+ declare optional known or extension keys in `hello`, and the server
14
+ advertises supported baseline capabilities in `welcome`. Unknown client
15
+ capability keys may be ignored.
16
+ contact:
17
+ name: Arcane Machine
18
+ url: https://github.com/arcanemachine/inter-agent
19
+ email: arcanemachine@gmail.com
20
+ license:
21
+ name: MIT
22
+ url: https://opensource.org/license/mit
23
+ tags:
24
+ - name: agent-coordination
25
+ defaultContentType: application/json
26
+ servers:
27
+ default:
28
+ url: '{host}:{port}'
29
+ protocol: ws
30
+ description: >
31
+ The resolved local endpoint. Use wss with the same host and port when
32
+ TLS is enabled.
33
+ variables:
34
+ host:
35
+ default: 127.0.0.1
36
+ port:
37
+ default: '16837'
38
+ channels:
39
+ /:
40
+ publish:
41
+ operationId: clientToServer
42
+ message:
43
+ oneOf:
44
+ - $ref: '#/components/messages/Hello'
45
+ - $ref: '#/components/messages/AuthResponse'
46
+ - $ref: '#/components/messages/Send'
47
+ - $ref: '#/components/messages/Broadcast'
48
+ - $ref: '#/components/messages/Ping'
49
+ - $ref: '#/components/messages/Bye'
50
+ - $ref: '#/components/messages/List'
51
+ - $ref: '#/components/messages/Shutdown'
52
+ - $ref: '#/components/messages/Kick'
53
+ - $ref: '#/components/messages/Custom'
54
+ - $ref: '#/components/messages/Subscribe'
55
+ - $ref: '#/components/messages/Unsubscribe'
56
+ - $ref: '#/components/messages/Publish'
57
+ - $ref: '#/components/messages/Channels'
58
+ subscribe:
59
+ operationId: serverToClient
60
+ message:
61
+ oneOf:
62
+ - $ref: '#/components/messages/AuthChallenge'
63
+ - $ref: '#/components/messages/Welcome'
64
+ - $ref: '#/components/messages/Msg'
65
+ - $ref: '#/components/messages/Pong'
66
+ - $ref: '#/components/messages/Error'
67
+ - $ref: '#/components/messages/ListOk'
68
+ - $ref: '#/components/messages/ShutdownOk'
69
+ - $ref: '#/components/messages/KickOk'
70
+ - $ref: '#/components/messages/SubscribeOk'
71
+ - $ref: '#/components/messages/UnsubscribeOk'
72
+ - $ref: '#/components/messages/ChannelsOk'
73
+ components:
74
+ schemas:
75
+ Hello:
76
+ $ref: './schemas/hello.json'
77
+ AuthChallenge:
78
+ $ref: './schemas/auth_challenge.json'
79
+ AuthResponse:
80
+ $ref: './schemas/auth_response.json'
81
+ Welcome:
82
+ $ref: './schemas/welcome.json'
83
+ Send:
84
+ $ref: './schemas/send.json'
85
+ Broadcast:
86
+ $ref: './schemas/broadcast.json'
87
+ Ping:
88
+ $ref: './schemas/ping.json'
89
+ Pong:
90
+ $ref: './schemas/pong.json'
91
+ Bye:
92
+ $ref: './schemas/bye.json'
93
+ Msg:
94
+ $ref: './schemas/msg.json'
95
+ Error:
96
+ $ref: './schemas/error.json'
97
+ List:
98
+ $ref: './schemas/list.json'
99
+ ListOk:
100
+ $ref: './schemas/list_ok.json'
101
+ Shutdown:
102
+ $ref: './schemas/shutdown.json'
103
+ ShutdownOk:
104
+ $ref: './schemas/shutdown_ok.json'
105
+ Kick:
106
+ $ref: './schemas/kick.json'
107
+ KickOk:
108
+ $ref: './schemas/kick_ok.json'
109
+ Custom:
110
+ $ref: './schemas/custom.json'
111
+ Subscribe:
112
+ $ref: './schemas/subscribe.json'
113
+ SubscribeOk:
114
+ $ref: './schemas/subscribe_ok.json'
115
+ Unsubscribe:
116
+ $ref: './schemas/unsubscribe.json'
117
+ UnsubscribeOk:
118
+ $ref: './schemas/unsubscribe_ok.json'
119
+ Publish:
120
+ $ref: './schemas/publish.json'
121
+ Channels:
122
+ $ref: './schemas/channels.json'
123
+ ChannelsOk:
124
+ $ref: './schemas/channels_ok.json'
125
+ messages:
126
+ Hello:
127
+ messageId: inter-agent.hello
128
+ payload:
129
+ $ref: '#/components/schemas/Hello'
130
+ AuthChallenge:
131
+ messageId: inter-agent.auth-challenge
132
+ payload:
133
+ $ref: '#/components/schemas/AuthChallenge'
134
+ AuthResponse:
135
+ messageId: inter-agent.auth-response
136
+ payload:
137
+ $ref: '#/components/schemas/AuthResponse'
138
+ Welcome:
139
+ messageId: inter-agent.welcome
140
+ payload:
141
+ $ref: '#/components/schemas/Welcome'
142
+ Send:
143
+ messageId: inter-agent.send
144
+ payload:
145
+ $ref: '#/components/schemas/Send'
146
+ Broadcast:
147
+ messageId: inter-agent.broadcast
148
+ payload:
149
+ $ref: '#/components/schemas/Broadcast'
150
+ Ping:
151
+ messageId: inter-agent.ping
152
+ payload:
153
+ $ref: '#/components/schemas/Ping'
154
+ Pong:
155
+ messageId: inter-agent.pong
156
+ payload:
157
+ $ref: '#/components/schemas/Pong'
158
+ Bye:
159
+ messageId: inter-agent.bye
160
+ payload:
161
+ $ref: '#/components/schemas/Bye'
162
+ Msg:
163
+ messageId: inter-agent.msg
164
+ payload:
165
+ $ref: '#/components/schemas/Msg'
166
+ Error:
167
+ messageId: inter-agent.error
168
+ payload:
169
+ $ref: '#/components/schemas/Error'
170
+ List:
171
+ messageId: inter-agent.list
172
+ payload:
173
+ $ref: '#/components/schemas/List'
174
+ ListOk:
175
+ messageId: inter-agent.list-ok
176
+ payload:
177
+ $ref: '#/components/schemas/ListOk'
178
+ Shutdown:
179
+ messageId: inter-agent.shutdown
180
+ payload:
181
+ $ref: '#/components/schemas/Shutdown'
182
+ ShutdownOk:
183
+ messageId: inter-agent.shutdown-ok
184
+ payload:
185
+ $ref: '#/components/schemas/ShutdownOk'
186
+ Kick:
187
+ messageId: inter-agent.kick
188
+ payload:
189
+ $ref: '#/components/schemas/Kick'
190
+ KickOk:
191
+ messageId: inter-agent.kick-ok
192
+ payload:
193
+ $ref: '#/components/schemas/KickOk'
194
+ Custom:
195
+ messageId: inter-agent.custom
196
+ payload:
197
+ $ref: '#/components/schemas/Custom'
198
+ Subscribe:
199
+ messageId: inter-agent.subscribe
200
+ payload:
201
+ $ref: '#/components/schemas/Subscribe'
202
+ SubscribeOk:
203
+ messageId: inter-agent.subscribe-ok
204
+ payload:
205
+ $ref: '#/components/schemas/SubscribeOk'
206
+ Unsubscribe:
207
+ messageId: inter-agent.unsubscribe
208
+ payload:
209
+ $ref: '#/components/schemas/Unsubscribe'
210
+ UnsubscribeOk:
211
+ messageId: inter-agent.unsubscribe-ok
212
+ payload:
213
+ $ref: '#/components/schemas/UnsubscribeOk'
214
+ Publish:
215
+ messageId: inter-agent.publish
216
+ payload:
217
+ $ref: '#/components/schemas/Publish'
218
+ Channels:
219
+ messageId: inter-agent.channels
220
+ payload:
221
+ $ref: '#/components/schemas/Channels'
222
+ ChannelsOk:
223
+ messageId: inter-agent.channels-ok
224
+ payload:
225
+ $ref: '#/components/schemas/ChannelsOk'
@@ -0,0 +1,28 @@
1
+ # Error Codes
2
+
3
+ Protocol errors are returned as `{"op":"error","code":"...","message":"..."}`. The `code` field is stable for clients and adapters; `message` is human-readable context and may vary.
4
+
5
+ | Code | Trigger condition | Client expectation |
6
+ | --- | --- | --- |
7
+ | `PROTOCOL_ERROR` | The first frame is not `hello`, a frame is invalid JSON, a frame is not a JSON object, or authenticated `hello.capabilities` is missing or not an object. | Treat the connection as invalid and reconnect with a valid protocol frame. |
8
+ | `AUTH_FAILED` | Challenge-response auth is missing, malformed, or proves the client does not know the shared secret. | Do not retry until server and client secret configuration has been corrected; see the secret rotation procedure in `SECURITY.md`. |
9
+ | `TOO_MANY_CONNECTIONS` | A valid connection attempt would exceed the configured active connection limit. | Close unused sessions or increase the local connection limit. |
10
+ | `BAD_ROLE` | `hello.role` is missing or is not `agent` or `control`, or an agent-role session attempts a control-only operation such as `shutdown`. | Send a valid role or use a control-role connection for control-only operations. |
11
+ | `BAD_SESSION` | `hello.session_id` is missing, empty, or not a string. | Generate and send a string session ID. |
12
+ | `SESSION_TAKEN` | `hello.session_id` is already active on another connection. | Reconnect after the previous connection closes or generate a new session ID. |
13
+ | `BAD_NAME` | An agent `hello.name` is missing or fails routing-name validation. | Choose a lowercase routing name matching the documented name format. |
14
+ | `BAD_LABEL` | `hello.label` is present but is neither a string nor `null`. | Omit the label, send `null`, or send a string display label. |
15
+ | `NAME_TAKEN` | An agent routing name is already connected. | Choose a different routing name or disconnect the existing session. |
16
+ | `UNKNOWN_OP` | A post-handshake frame uses an unsupported `op`. | Use a supported core operation or an extension envelope. |
17
+ | `BAD_TEXT` | A `send`, `broadcast`, or `publish` operation has a non-string `text`. | Send message text as a string. |
18
+ | `BAD_FROM_NAME` | A message operation has a non-string `from_name`. | Omit `from_name` or send it as a string. |
19
+ | `BAD_CUSTOM_TYPE` | A `custom` operation has a missing, empty, non-string, or oversized `custom_type`. | Send a non-empty custom type within the configured byte limit. |
20
+ | `TEXT_TOO_LARGE` | A direct or broadcast message exceeds configured UTF-8 byte text limits (`INTER_AGENT_DIRECT_MAX` or `INTER_AGENT_BROADCAST_MAX`). | Shorten or split the message. |
21
+ | `CUSTOM_PAYLOAD_TOO_LARGE` | A `custom.payload` exceeds the configured JSON-encoded UTF-8 byte limit (`INTER_AGENT_CUSTOM_PAYLOAD_MAX`). | Shorten or split the custom payload. |
22
+ | `UNKNOWN_TARGET` | A direct `send` or targeted `custom` operation names no connected target. | Refresh session presence and retry with a connected routing name. |
23
+ | `AMBIGUOUS_TARGET` | A direct `send` or targeted `custom` operation uses a prefix that matches multiple connected targets. | Retry with a longer prefix or exact routing name. |
24
+ | `BAD_CHANNEL` | A channel operation has a missing, non-string, syntactically invalid, or oversized `channel` value. | Send a valid channel name matching the documented format and byte limit. |
25
+ | `CHANNEL_LIMIT_REACHED` | A subscription would exceed the per-session subscription limit (`INTER_AGENT_SUBSCRIPTIONS_MAX`) or creating a channel would exceed the server channel limit (`INTER_AGENT_CHANNELS_MAX`). | Leave unused channels or increase the configured limit. |
26
+ | `NOT_SUBSCRIBED` | An `unsubscribe` targets a channel the session is not subscribed to. | Subscribe before unsubscribing, or ignore if already unsubscribed. |
27
+ | `UNKNOWN_CHANNEL` | A `publish` targets a channel with no active subscribers. | Subscribe at least one session to the channel before publishing. |
28
+ | `KICKED` | A control-role caller removed this connection with `kick`. The error is sent immediately before the target WebSocket is closed. | Treat the error as terminal for this listener process: stop automatic reconnects. The routing name is free immediately and may register again through an explicit later connect or host/session reload/restart; there is no ban or blocklist. |
@@ -0,0 +1,6 @@
1
+ {
2
+ "op": "auth_challenge",
3
+ "method": "hmac-sha256",
4
+ "server_nonce": "server-nonce",
5
+ "server_proof": "server-proof-hex"
6
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "op": "auth_response",
3
+ "client_proof": "client-proof-hex"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "op": "broadcast",
3
+ "text": "build is green"
4
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "op": "bye"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "op": "channels"
3
+ }