@passioncode-ai/fabric-agent-adapter 0.73.0 → 0.75.0

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 (43) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/README.md +11 -7
  3. package/SECURITY.md +17 -0
  4. package/package.json +1 -1
  5. package/plugins/fabric-agent-adapter/.claude-plugin/plugin.json +1 -1
  6. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/SKILL.md +3 -3
  7. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/dashboard-links.md +6 -2
  8. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/operator-channel-and-repository.md +3 -2
  9. package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py +2 -2
  10. package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +16 -17
  11. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/support-agent/README.md +14 -2
  12. package/plugins/fabric-agent-adapter/skills/building-fabric-services/recipes/support-agent/channel-agent.example.json +1 -1
  13. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/board.md +4 -1
  14. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/connectors.md +2 -1
  15. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard-links.md +6 -2
  16. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/delegation.md +3 -1
  17. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/interop.md +3 -1
  18. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/kit-modules.md +1 -0
  19. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/lifecycle.md +10 -4
  20. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md +33 -4
  21. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/surfaces-and-auth.md +6 -4
  22. package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/usage.md +4 -2
  23. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_dashboard_layout.mjs +19 -2
  24. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py +37 -3
  25. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service_rules.py +38 -0
  26. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-http.mjs +53 -3
  27. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-hub.mjs +16 -5
  28. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-peer-owner.mjs +545 -0
  29. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-supervisors.mjs +43 -7
  30. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_http.py +29 -4
  31. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_hub.py +13 -4
  32. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_peer_owner.py +845 -0
  33. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_supervisors.py +35 -5
  34. package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/kit.json +214 -9
  35. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +8 -5
  36. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/agents-that-answer-people.md +6 -2
  37. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/communication-agent-template.md +380 -0
  38. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/dashboard-links.md +6 -2
  39. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/models-and-providers.md +8 -2
  40. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/operator-channel-and-repository.md +3 -2
  41. package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/references/practices.md +1 -1
  42. package/plugins/fabric-agent-adapter/skills/working-with-fabric/SKILL.md +1 -1
  43. package/plugins/fabric-agent-adapter/skills/working-with-fabric/scripts/fabric_session_env.py +1 -1
@@ -3,6 +3,7 @@ removed without touching what the operator turned off; release pruning (LC-15).
3
3
  (FAA-65, layer L3)."""
4
4
  from __future__ import annotations
5
5
 
6
+ import http.client
6
7
  import json
7
8
  import os
8
9
  import plistlib
@@ -13,14 +14,16 @@ import sys
13
14
  import tempfile
14
15
  import time
15
16
  import urllib.error
17
+ import urllib.parse
16
18
  import urllib.request
17
19
  from pathlib import Path, PurePath
18
- from typing import Any, Callable, Dict, List, Optional, Sequence
20
+ from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple
19
21
 
20
22
  import sys as _sys # noqa: E402
21
23
  from pathlib import Path as _Path # noqa: E402
22
24
  if str(_Path(__file__).resolve().parent) not in _sys.path: # the kit loads from any working directory (FAA-65)
23
25
  _sys.path.insert(0, str(_Path(__file__).resolve().parent))
26
+ import fabric_peer_owner as _po # noqa: E402 - the listener's owner (DEC-0154 HA-2)
24
27
  from fabric_base import (
25
28
  DRAIN_SECONDS,
26
29
  SUPERVISOR_ENV,
@@ -304,12 +307,34 @@ def launchd_loaded(label: str) -> bool:
304
307
  return _launchctl("print", "%s/%s" % (_domain(), label)).returncode == 0
305
308
 
306
309
 
307
- def fetch_well_known(origin: str, timeout: float = 2.0) -> Optional[Dict[str, Any]]:
310
+ def _read_well_known(origin: str, timeout: float = 2.0) -> Tuple[Optional[Dict[str, Any]], Optional[str]]:
311
+ """(the well-known answer or None, why the listener was refused or None). A loopback origin is read only on a
312
+ connection whose server end is this OS account's process (DEC-0154 HA-2): another account's, root's, or one whose
313
+ owner cannot be told is `foreign-user`, never this service's answer."""
314
+ parts = urllib.parse.urlsplit(origin)
315
+ if parts.scheme == "http" and parts.hostname == "127.0.0.1" and parts.port:
316
+ conn = _po.CheckedHTTPConnection("127.0.0.1", parts.port, timeout=timeout)
317
+ try:
318
+ conn.request("GET", "/.well-known/fabric-service", headers={"Host": "127.0.0.1:%d" % parts.port})
319
+ response = conn.getresponse()
320
+ return (json.loads(response.read().decode()) if response.status == 200 else None), None
321
+ except _po.ListenerRefused as exc:
322
+ return None, "foreign-user: %s" % exc
323
+ except (OSError, ValueError, http.client.HTTPException):
324
+ return None, None
325
+ finally:
326
+ conn.close()
308
327
  try:
309
328
  with urllib.request.urlopen(origin + "/.well-known/fabric-service", timeout=timeout) as response:
310
- return json.loads(response.read().decode())
329
+ return json.loads(response.read().decode()), None
311
330
  except (urllib.error.URLError, OSError, ValueError):
312
- return None
331
+ return None, None
332
+
333
+
334
+ def fetch_well_known(origin: str, timeout: float = 2.0) -> Optional[Dict[str, Any]]:
335
+ """The well-known answer at `origin`, or None: nothing answers, the answer is not JSON, or the listener is not this
336
+ OS account's process (DEC-0154 HA-2)."""
337
+ return _read_well_known(origin, timeout)[0]
313
338
 
314
339
 
315
340
  _OVERRIDE_ROW = re.compile(r'^\s*"([^"]+)"\s*=>\s*(\S+)\s*\Z')
@@ -367,11 +392,16 @@ def launchd_install(label: str, plist_path: Path, plist_bytes: bytes, *, origin:
367
392
  else:
368
393
  raise ServiceError("launchctl bootstrap failed: %s" % last)
369
394
  deadline = time.time() + timeout
395
+ foreign = None
370
396
  while time.time() < deadline:
371
- doc = fetch_well_known(origin)
397
+ doc, foreign = _read_well_known(origin)
372
398
  if doc and doc.get("service", {}).get("id") == service_id and doc.get("service", {}).get("instance") == instance:
373
399
  return doc
374
400
  time.sleep(0.5)
401
+ if foreign:
402
+ # DEC-0154 HA-2 and service.md's Install row: a listener of another account is never a successful install.
403
+ raise ServiceError("%s is not this service's: %s (DEC-0154 HA-2); the port is another OS account's or its owner "
404
+ "cannot be told." % (origin, foreign))
375
405
  raise ServiceError("%s did not answer as %s.%s within %.0f s; read its log." % (origin, service_id, instance, timeout))
376
406
 
377
407
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fabric-service-kit",
3
- "version": "0.73.0",
3
+ "version": "0.75.0",
4
4
  "about": "The service kit's modules in dependency order: a module imports only modules listed before it. Written by fabric_kit.py build; edit the order and layers by hand, never the digests.",
5
5
  "python": [
6
6
  {
@@ -33,6 +33,13 @@
33
33
  "imports": [],
34
34
  "sha256": "53c5df8d6f2c87433c288853bfaad9a43f544789bdf1e39bda8d3ff14485c89d"
35
35
  },
36
+ {
37
+ "module": "fabric_peer_owner",
38
+ "file": "fabric_peer_owner.py",
39
+ "layer": "L0",
40
+ "imports": [],
41
+ "sha256": "3d66b1084c0b8b11ccfc4c66c1b32751ea237df03d864bfc0661d1a2e4665338"
42
+ },
36
43
  {
37
44
  "module": "fabric_crypto",
38
45
  "file": "fabric_crypto.py",
@@ -328,9 +335,10 @@
328
335
  "fabric_base",
329
336
  "fabric_lock",
330
337
  "fabric_paths",
338
+ "fabric_peer_owner",
331
339
  "fabric_secrets"
332
340
  ],
333
- "sha256": "3c5b2e8c310738720b1c1b779be4710e90251013d9be4c68f9952edc0bf55d5f"
341
+ "sha256": "bf5aac4034468f966cefae28dcbdca7f04f42fe73aefd1bac1b377cf4bda2b74"
334
342
  },
335
343
  {
336
344
  "module": "fabric_service",
@@ -406,9 +414,10 @@
406
414
  "layer": "L4",
407
415
  "imports": [
408
416
  "fabric_estate",
417
+ "fabric_peer_owner",
409
418
  "fabric_service"
410
419
  ],
411
- "sha256": "b9ac852e601b1d54cf61351677a628afc69faeed7d1fc74ebe541c1cf38e0c2a"
420
+ "sha256": "c261a81616c52f603eb28cc12ec4034dc479f0517328a65f0dc48d436cf0708b"
412
421
  },
413
422
  {
414
423
  "module": "fabric_board_shapes",
@@ -482,9 +491,10 @@
482
491
  "file": "fabric_http.py",
483
492
  "layer": "L4",
484
493
  "imports": [
485
- "fabric_jsvalue"
494
+ "fabric_jsvalue",
495
+ "fabric_peer_owner"
486
496
  ],
487
- "sha256": "8b443477dc29d5a1fe908b9dccaf68f05fab837eae0670074051a1dd2dfb71ad"
497
+ "sha256": "e02b049b40eaabd994d93c7b084ee34ef3a78b5cbb61303b8e519b906af3c27a"
488
498
  },
489
499
  {
490
500
  "module": "fabric_openrouter",
@@ -527,6 +537,13 @@
527
537
  "imports": [],
528
538
  "sha256": "5822a7e25ecf2e87b5bab4f99c1074af7379d8b49e2784283b5d7d8c25022cde"
529
539
  },
540
+ {
541
+ "module": "fabric-peer-owner",
542
+ "file": "fabric-peer-owner.mjs",
543
+ "layer": "L0",
544
+ "imports": [],
545
+ "sha256": "0e65d59bc1048a5635c8ac04e73fe4fd1f34094902ced1580859017e5ca5a991"
546
+ },
530
547
  {
531
548
  "module": "fabric-crypto",
532
549
  "file": "fabric-crypto.mjs",
@@ -821,9 +838,10 @@
821
838
  "fabric-base",
822
839
  "fabric-lock",
823
840
  "fabric-paths",
841
+ "fabric-peer-owner",
824
842
  "fabric-secrets"
825
843
  ],
826
- "sha256": "d45c38de0cb3ed85e083496c2d3c51dab004454accdd87f4762a512a6d442573"
844
+ "sha256": "e33b2b8916aeed617eee6233e05bd637bb4ecd87064248fd7ea08fdfcd45d375"
827
845
  },
828
846
  {
829
847
  "module": "fabric-service",
@@ -891,9 +909,10 @@
891
909
  "layer": "L4",
892
910
  "imports": [
893
911
  "fabric-estate",
912
+ "fabric-peer-owner",
894
913
  "fabric-service"
895
914
  ],
896
- "sha256": "c005115a864cfd67daa4862097bb14acfe5a60bf653897e5bf8a570dd80f1070"
915
+ "sha256": "73ab07f72320a50042f39b52893b563157be2ac94615614416df45a796eac988"
897
916
  },
898
917
  {
899
918
  "module": "fabric-board-shapes",
@@ -966,8 +985,10 @@
966
985
  "module": "fabric-http",
967
986
  "file": "fabric-http.mjs",
968
987
  "layer": "L4",
969
- "imports": [],
970
- "sha256": "317d7668c291570d4d93bc73295312f2853eb93940f4cf754a4a4619cb87ace9"
988
+ "imports": [
989
+ "fabric-peer-owner"
990
+ ],
991
+ "sha256": "b83b4c0c208763d56c3eebda5fe9e4a46d595cd91227699bf6876e65a3c7f9b9"
971
992
  },
972
993
  {
973
994
  "module": "fabric-openrouter",
@@ -5856,6 +5877,190 @@
5856
5877
  "fabric-openrouter.mjs": "6041f3ab30f516658e1dbab4897a651cc8509b2136cfa8e769802c6b40ec2f35",
5857
5878
  "fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
5858
5879
  "share-registration.schema.json": "34b3997eeaf936ebc861342a23045634a7c18c19f01d7ed4198310d81989f5b0"
5880
+ },
5881
+ "0.74.0": {
5882
+ "fabric_jsvalue.py": "052f1b40bab18600b3731dbdca27cbff17588c21d9458fa6241efd1340d0e09a",
5883
+ "fabric_time.py": "588f383da4ac6a243ea95b6ffc3a0aa99ca94245732dc4937734f190b7af4ae9",
5884
+ "fabric_identifiers.py": "0fd814d521ac3aa39907458265870753046a73f48af3d8581ab864b93b211607",
5885
+ "fabric_secrets.py": "53c5df8d6f2c87433c288853bfaad9a43f544789bdf1e39bda8d3ff14485c89d",
5886
+ "fabric_peer_owner.py": "3d66b1084c0b8b11ccfc4c66c1b32751ea237df03d864bfc0661d1a2e4665338",
5887
+ "fabric_crypto.py": "9c34aee20dbe4d6742e4fdbaab68ceb934bbe7dbd3a904c0010824ace16cdeaa",
5888
+ "fabric_base.py": "f62bcc2ed9912660fa875d27a09f60867260cc4925f79873501fd9620be59611",
5889
+ "fabric_platform.py": "a9350dff55ef0fb3a23cdb4d0320a15868b15a8deb10d2eb74d72c58740c284b",
5890
+ "fabric_paths.py": "8a1ee742f80f436e9f28c61b4f049a9545de2a9e0d66bfc61faa6ee5d1ba3734",
5891
+ "fabric_estate_rules.py": "8b36a7f4108d9c2b1fb38c8bff344778c807bed631a99b4a563ecb0a49c10b1c",
5892
+ "fabric_estate.py": "0737ae1d1bb12586bae49de1f15ef1348bc207b5007cced9dad4c55bb5870874",
5893
+ "fabric_mandate.py": "fb19ce5359606bd6e3352ab02b2a12f49605ec6e5c49b55cce1f79c831325044",
5894
+ "fabric_delegation.py": "716f0ff7ac01095f54b24970beac1962128e8ff33026b243fc0467876142ab03",
5895
+ "fabric_share.py": "da36a466426fc29dd7dd40013167f3959a18375f8fedd228bf64f298cec1040c",
5896
+ "fabric_ceremonies.py": "a59e83cf4adb2669a9b98008e3d3a0cba991a35cbff97bc604fc82fe81cfd49f",
5897
+ "fabric_package_schema.py": "e623f0408d38e3343ed66222fb812907c6c52e1a286eb1c1176ab2e64640c9ad",
5898
+ "fabric_package.py": "1f2b9e73b2b32a7e1e887d4b69f87c6e21b4d1227ad924a235334223e6dd51ca",
5899
+ "fabric_protocols.py": "077c6f03f3b887a2e22d9ce6b5bd3750199d71a29d4c82b1d5af8a615b509d93",
5900
+ "fabric_actions.py": "ae21d1199614c4f74d1dcd1e0a87107a9d52434cd9e2d64aa24a7b1e196fb723",
5901
+ "fabric_connections.py": "7de55cb7d808f756d650effabfaa12027d40a5bd5d2f6d448c32969d47529ecb",
5902
+ "fabric_a2a.py": "8b01502131215bb4de1c01866187c56e99b791543923ed8577535573db33b919",
5903
+ "fabric_page_links.py": "1b57ea573c550e2f90d1ec3edcc655917ceaa0db9dd1635fccf422ec3024d25e",
5904
+ "fabric_lock.py": "dfaf92a7086cbb097d832a305869b7964e2d2a9da0e3365c8ec1685a7bb4fef9",
5905
+ "fabric_usage.py": "5cc2e03ccc5b06e81987ed7bc3eead7a7e6cbf1a7cb8e05c6c64315eed9d91b6",
5906
+ "fabric_backups.py": "1f3f0d7ecf361b29e9101e07f1c53e5dc304d598bf26fd59ec89f16b9fed2420",
5907
+ "fabric_descriptor.py": "c08c91ca0960c694ed7677e7e9247d6307c7b63f37a7e614db022c080cd92ccc",
5908
+ "fabric_context.py": "6ae311ddc7217a4aff915e7ce2646486931acd128462b7bebe4a52bbb5fbb6c7",
5909
+ "fabric_auth.py": "74ccc10239b65a3567cec5213a7b344cbd88d6eee1fd1c5f7be1d6daf985993c",
5910
+ "fabric_events.py": "cd94b186e2a8f8cb4ad2b6bd44d83ec5021933075e28c5d655f387f16dff42b8",
5911
+ "fabric_logs.py": "86dc55bfafa2a57264722e2403510a249b95de0e4a722b2e4bc3948e3bd93da9",
5912
+ "fabric_supervisors.py": "bf5aac4034468f966cefae28dcbdca7f04f42fe73aefd1bac1b377cf4bda2b74",
5913
+ "fabric_service.py": "4b13f90aa26881fbfe0d9f3077fbb3552f3ce0a3c59279d6baa92df872867d8d",
5914
+ "fabric_profiles.py": "26e21ec29c016000f8ca8053b7b489184854a73be1b7fdc0a18d12990203db9b",
5915
+ "fabric_interop_rules.py": "9bdb7989e57b9d0b0d15eb9982d396499823a5e2c528230b71c67866c736e0f5",
5916
+ "fabric_interop.py": "d27e31834611a37cf2a117746f2f60fc187ccc48718eb546ff923c5d0fce7dea",
5917
+ "fabric_hub.py": "c261a81616c52f603eb28cc12ec4034dc479f0517328a65f0dc48d436cf0708b",
5918
+ "fabric_board_shapes.py": "0a0e8d3d40e33dfd8c457aedb85330b2ff25f8c49a33eb6cbd5a5cc8a5007f7e",
5919
+ "fabric_board_link.py": "052bc3c474ece835bb428c37ca864810d04e394d991ddb9c93989a7a825073a5",
5920
+ "fabric_board_slots.py": "92b065e3df935547cf46653245f1129e4a1f8b59b0a41e8fa9ffdc41596ee592",
5921
+ "fabric_board_session.py": "1fd3c3884f3044b56a40f78b33ff88dcac9272284f6681ea359c662879826f7e",
5922
+ "fabric_board_fixture.py": "69761ce205ec640762ec9b591c6903e5a87f844e8d423b041681924027e39d1e",
5923
+ "fabric_board.py": "f86c40b8291f8c818f6924910f4022b013d5fd107abaf8825dd0aa6c5e418638",
5924
+ "fabric_http.py": "e02b049b40eaabd994d93c7b084ee34ef3a78b5cbb61303b8e519b906af3c27a",
5925
+ "fabric_openrouter.py": "d06a40f83f2fb8bd441ab3485ae882f1fbdd9cd7a9c1ec175eb47cb8ae2cce81",
5926
+ "fabric-jsvalue.mjs": "dfbdb8c41584972c9389750a41719374a1cfc5652ed438dd1623025190b0106e",
5927
+ "fabric-time.mjs": "3ff932069038a720df1c68c6492976906737b2e67e5c12d9c81c418597f661de",
5928
+ "fabric-identifiers.mjs": "a18c2a501a4aa170bfd3d99e571ad6b7662649b4d3b9d2a540c002ea42811bbf",
5929
+ "fabric-secrets.mjs": "5822a7e25ecf2e87b5bab4f99c1074af7379d8b49e2784283b5d7d8c25022cde",
5930
+ "fabric-peer-owner.mjs": "0e65d59bc1048a5635c8ac04e73fe4fd1f34094902ced1580859017e5ca5a991",
5931
+ "fabric-crypto.mjs": "038e03689701e3c9721a1e7f8e0a4d02a52d6a5d1661b0dc84035edc3ebbfcf6",
5932
+ "fabric-base.mjs": "7804b2df7715dbbf9702a9b61b6b8cef2110f9a52b04cabd8fb0a66458d87512",
5933
+ "fabric-platform.mjs": "a8119d95ebba4d589a9e401f5d6fc8dda62d59d44e4c1ff811d97fac3771ac0c",
5934
+ "fabric-paths.mjs": "aa630d611e748a899e7043480f4a4e46b444f2e15ff945f30c2fbef21c1ceea5",
5935
+ "fabric-estate-rules.mjs": "7476be71174aa5b1026134f2b335abf647feaa55584e2f9de8618e3054aa8e1e",
5936
+ "fabric-estate.mjs": "e8a2e62d2313121e6cb502f6e6abad94d1d546a44b4d9b3ce2be29e7808e8cf3",
5937
+ "fabric-mandate.mjs": "b70f3de03a659e60bba7b5a0580b3582825cd7b8a8e30a28c79621919ec5b7bb",
5938
+ "fabric-delegation.mjs": "8f63a63aab9a8746b7f664720b87e9398137d01b8d50880974d5070038e414a0",
5939
+ "fabric-share.mjs": "bfb26581c21ad984c2a337da02429f9f3a165cc582f8ba48de4d3dfb7d163a59",
5940
+ "fabric-ceremonies.mjs": "117d4374c9e95c930a38de7adbd4323774798f4fe6ec6f24afcd6f2c7298ca44",
5941
+ "fabric-package-schema.mjs": "cd28092375db0fc21ffab1f0bb7794f7f8979ee08c64d3b9faf4b3845357caa6",
5942
+ "fabric-package.mjs": "8cfb32eebbd4e1bcf28a6e4437344ae2dd54479b0e7c820f002e9f94ab9ecaad",
5943
+ "fabric-protocols.mjs": "a560b7d6eb0d26204c5536711c3dda9daae90cc91e07cdc75412e75c86272767",
5944
+ "fabric-actions.mjs": "06e42f5e24c96311d5417d0d1effa93479ef7128a7ab139903b2bcf59253f6be",
5945
+ "fabric-connections.mjs": "303432e547ce563e90ca9ffcd827f5612f51d3582929834e1add0fdaf6485dcc",
5946
+ "fabric-a2a.mjs": "51b72fe1d80649d659fcad3a8f96370db3476c4a7b30cbabd8522c138be69346",
5947
+ "fabric-page-links.mjs": "a8834926e9d4bbf7c4857f551451d2ebf6ac8873bbccaaf89c5e30cf45b17ee6",
5948
+ "fabric-lock.mjs": "02cf833c97a07a8b3c788f9c93f70c4b9c9066efa25318dccf0038e0fc79717f",
5949
+ "fabric-usage.mjs": "1c4d18004639409624ac3516a02f2b60bbf55abdb612e9a96c37e83666eb87a7",
5950
+ "fabric-backups.mjs": "cfd8c9085e3d597a783099c2bd2ffe2f3faa0daaadab46dedd30523894cfeb06",
5951
+ "fabric-descriptor.mjs": "7c0ef7d245c037eb9e859ab481f6e66fb3e5ef2cf6d1e0a8d32b6d303097ca43",
5952
+ "fabric-context.mjs": "1112d695e872f9825cbc94f08484974bff3880087bc29b8be59f885f03e8f7be",
5953
+ "fabric-auth.mjs": "10ff37a39f9e3adb4d0f05db66c45f49b10eef582e9220c213907964109d7e52",
5954
+ "fabric-events.mjs": "c463d6ffcae24229a5c608d8fcea4268d2ccc5024b19fa10e5a452284068fa71",
5955
+ "fabric-logs.mjs": "58467e5719c16e099d05bbedec47a95712506ab03c33f3cd4be1252e8498a946",
5956
+ "fabric-supervisors.mjs": "e33b2b8916aeed617eee6233e05bd637bb4ecd87064248fd7ea08fdfcd45d375",
5957
+ "fabric-service.mjs": "297fef11ac76dc831d12d24c5581b7a93587c300c20664db703b3f924c0f9f1a",
5958
+ "fabric-profiles.mjs": "314376cf2deb87f235fb18b11d3b532e211f585b9af0a9302b5f4cc39971b532",
5959
+ "fabric-interop-rules.mjs": "b4e386c359a48e49ffff8a842215760c18a7c98a0af4754a808a35fb2820d458",
5960
+ "fabric-interop.mjs": "989040aed33b2712a258244192bdf70e811a51076aa1b62f2adc2a6db051dbed",
5961
+ "fabric-hub.mjs": "73ab07f72320a50042f39b52893b563157be2ac94615614416df45a796eac988",
5962
+ "fabric-board-shapes.mjs": "c1db7b7bd0d58d82bb6d8dfbc3cd1547a256a333052d367e82ff1b3edf2804d7",
5963
+ "fabric-board-link.mjs": "6e7d51f4fd9730d93455f50dd30e97907b8b9e1ca65a1d69f036f2e8ec05cc0d",
5964
+ "fabric-board-slots.mjs": "fc77a3c6e62aa18575568bef4f703cce2edaba8cef648813ebcdbb21bdc27a11",
5965
+ "fabric-board-session.mjs": "18555962e5f6d18080a3e7971c4c6640452542f6042d07917e7ebc073721c415",
5966
+ "fabric-board-fixture.mjs": "83c4b7e33ee47b68385faf2569d38d5c8a0c5cb0f8656090f41e1b0eed2f436e",
5967
+ "fabric-board.mjs": "15fbb4441fcf7d2f285375b75de64ad6cffea129c515084c110245376b07775f",
5968
+ "fabric-http.mjs": "b83b4c0c208763d56c3eebda5fe9e4a46d595cd91227699bf6876e65a3c7f9b9",
5969
+ "fabric-openrouter.mjs": "6041f3ab30f516658e1dbab4897a651cc8509b2136cfa8e769802c6b40ec2f35",
5970
+ "fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
5971
+ "share-registration.schema.json": "34b3997eeaf936ebc861342a23045634a7c18c19f01d7ed4198310d81989f5b0"
5972
+ },
5973
+ "0.75.0": {
5974
+ "fabric_jsvalue.py": "052f1b40bab18600b3731dbdca27cbff17588c21d9458fa6241efd1340d0e09a",
5975
+ "fabric_time.py": "588f383da4ac6a243ea95b6ffc3a0aa99ca94245732dc4937734f190b7af4ae9",
5976
+ "fabric_identifiers.py": "0fd814d521ac3aa39907458265870753046a73f48af3d8581ab864b93b211607",
5977
+ "fabric_secrets.py": "53c5df8d6f2c87433c288853bfaad9a43f544789bdf1e39bda8d3ff14485c89d",
5978
+ "fabric_peer_owner.py": "3d66b1084c0b8b11ccfc4c66c1b32751ea237df03d864bfc0661d1a2e4665338",
5979
+ "fabric_crypto.py": "9c34aee20dbe4d6742e4fdbaab68ceb934bbe7dbd3a904c0010824ace16cdeaa",
5980
+ "fabric_base.py": "f62bcc2ed9912660fa875d27a09f60867260cc4925f79873501fd9620be59611",
5981
+ "fabric_platform.py": "a9350dff55ef0fb3a23cdb4d0320a15868b15a8deb10d2eb74d72c58740c284b",
5982
+ "fabric_paths.py": "8a1ee742f80f436e9f28c61b4f049a9545de2a9e0d66bfc61faa6ee5d1ba3734",
5983
+ "fabric_estate_rules.py": "8b36a7f4108d9c2b1fb38c8bff344778c807bed631a99b4a563ecb0a49c10b1c",
5984
+ "fabric_estate.py": "0737ae1d1bb12586bae49de1f15ef1348bc207b5007cced9dad4c55bb5870874",
5985
+ "fabric_mandate.py": "fb19ce5359606bd6e3352ab02b2a12f49605ec6e5c49b55cce1f79c831325044",
5986
+ "fabric_delegation.py": "716f0ff7ac01095f54b24970beac1962128e8ff33026b243fc0467876142ab03",
5987
+ "fabric_share.py": "da36a466426fc29dd7dd40013167f3959a18375f8fedd228bf64f298cec1040c",
5988
+ "fabric_ceremonies.py": "a59e83cf4adb2669a9b98008e3d3a0cba991a35cbff97bc604fc82fe81cfd49f",
5989
+ "fabric_package_schema.py": "e623f0408d38e3343ed66222fb812907c6c52e1a286eb1c1176ab2e64640c9ad",
5990
+ "fabric_package.py": "1f2b9e73b2b32a7e1e887d4b69f87c6e21b4d1227ad924a235334223e6dd51ca",
5991
+ "fabric_protocols.py": "077c6f03f3b887a2e22d9ce6b5bd3750199d71a29d4c82b1d5af8a615b509d93",
5992
+ "fabric_actions.py": "ae21d1199614c4f74d1dcd1e0a87107a9d52434cd9e2d64aa24a7b1e196fb723",
5993
+ "fabric_connections.py": "7de55cb7d808f756d650effabfaa12027d40a5bd5d2f6d448c32969d47529ecb",
5994
+ "fabric_a2a.py": "8b01502131215bb4de1c01866187c56e99b791543923ed8577535573db33b919",
5995
+ "fabric_page_links.py": "1b57ea573c550e2f90d1ec3edcc655917ceaa0db9dd1635fccf422ec3024d25e",
5996
+ "fabric_lock.py": "dfaf92a7086cbb097d832a305869b7964e2d2a9da0e3365c8ec1685a7bb4fef9",
5997
+ "fabric_usage.py": "5cc2e03ccc5b06e81987ed7bc3eead7a7e6cbf1a7cb8e05c6c64315eed9d91b6",
5998
+ "fabric_backups.py": "1f3f0d7ecf361b29e9101e07f1c53e5dc304d598bf26fd59ec89f16b9fed2420",
5999
+ "fabric_descriptor.py": "c08c91ca0960c694ed7677e7e9247d6307c7b63f37a7e614db022c080cd92ccc",
6000
+ "fabric_context.py": "6ae311ddc7217a4aff915e7ce2646486931acd128462b7bebe4a52bbb5fbb6c7",
6001
+ "fabric_auth.py": "74ccc10239b65a3567cec5213a7b344cbd88d6eee1fd1c5f7be1d6daf985993c",
6002
+ "fabric_events.py": "cd94b186e2a8f8cb4ad2b6bd44d83ec5021933075e28c5d655f387f16dff42b8",
6003
+ "fabric_logs.py": "86dc55bfafa2a57264722e2403510a249b95de0e4a722b2e4bc3948e3bd93da9",
6004
+ "fabric_supervisors.py": "bf5aac4034468f966cefae28dcbdca7f04f42fe73aefd1bac1b377cf4bda2b74",
6005
+ "fabric_service.py": "4b13f90aa26881fbfe0d9f3077fbb3552f3ce0a3c59279d6baa92df872867d8d",
6006
+ "fabric_profiles.py": "26e21ec29c016000f8ca8053b7b489184854a73be1b7fdc0a18d12990203db9b",
6007
+ "fabric_interop_rules.py": "9bdb7989e57b9d0b0d15eb9982d396499823a5e2c528230b71c67866c736e0f5",
6008
+ "fabric_interop.py": "d27e31834611a37cf2a117746f2f60fc187ccc48718eb546ff923c5d0fce7dea",
6009
+ "fabric_hub.py": "c261a81616c52f603eb28cc12ec4034dc479f0517328a65f0dc48d436cf0708b",
6010
+ "fabric_board_shapes.py": "0a0e8d3d40e33dfd8c457aedb85330b2ff25f8c49a33eb6cbd5a5cc8a5007f7e",
6011
+ "fabric_board_link.py": "052bc3c474ece835bb428c37ca864810d04e394d991ddb9c93989a7a825073a5",
6012
+ "fabric_board_slots.py": "92b065e3df935547cf46653245f1129e4a1f8b59b0a41e8fa9ffdc41596ee592",
6013
+ "fabric_board_session.py": "1fd3c3884f3044b56a40f78b33ff88dcac9272284f6681ea359c662879826f7e",
6014
+ "fabric_board_fixture.py": "69761ce205ec640762ec9b591c6903e5a87f844e8d423b041681924027e39d1e",
6015
+ "fabric_board.py": "f86c40b8291f8c818f6924910f4022b013d5fd107abaf8825dd0aa6c5e418638",
6016
+ "fabric_http.py": "e02b049b40eaabd994d93c7b084ee34ef3a78b5cbb61303b8e519b906af3c27a",
6017
+ "fabric_openrouter.py": "d06a40f83f2fb8bd441ab3485ae882f1fbdd9cd7a9c1ec175eb47cb8ae2cce81",
6018
+ "fabric-jsvalue.mjs": "dfbdb8c41584972c9389750a41719374a1cfc5652ed438dd1623025190b0106e",
6019
+ "fabric-time.mjs": "3ff932069038a720df1c68c6492976906737b2e67e5c12d9c81c418597f661de",
6020
+ "fabric-identifiers.mjs": "a18c2a501a4aa170bfd3d99e571ad6b7662649b4d3b9d2a540c002ea42811bbf",
6021
+ "fabric-secrets.mjs": "5822a7e25ecf2e87b5bab4f99c1074af7379d8b49e2784283b5d7d8c25022cde",
6022
+ "fabric-peer-owner.mjs": "0e65d59bc1048a5635c8ac04e73fe4fd1f34094902ced1580859017e5ca5a991",
6023
+ "fabric-crypto.mjs": "038e03689701e3c9721a1e7f8e0a4d02a52d6a5d1661b0dc84035edc3ebbfcf6",
6024
+ "fabric-base.mjs": "7804b2df7715dbbf9702a9b61b6b8cef2110f9a52b04cabd8fb0a66458d87512",
6025
+ "fabric-platform.mjs": "a8119d95ebba4d589a9e401f5d6fc8dda62d59d44e4c1ff811d97fac3771ac0c",
6026
+ "fabric-paths.mjs": "aa630d611e748a899e7043480f4a4e46b444f2e15ff945f30c2fbef21c1ceea5",
6027
+ "fabric-estate-rules.mjs": "7476be71174aa5b1026134f2b335abf647feaa55584e2f9de8618e3054aa8e1e",
6028
+ "fabric-estate.mjs": "e8a2e62d2313121e6cb502f6e6abad94d1d546a44b4d9b3ce2be29e7808e8cf3",
6029
+ "fabric-mandate.mjs": "b70f3de03a659e60bba7b5a0580b3582825cd7b8a8e30a28c79621919ec5b7bb",
6030
+ "fabric-delegation.mjs": "8f63a63aab9a8746b7f664720b87e9398137d01b8d50880974d5070038e414a0",
6031
+ "fabric-share.mjs": "bfb26581c21ad984c2a337da02429f9f3a165cc582f8ba48de4d3dfb7d163a59",
6032
+ "fabric-ceremonies.mjs": "117d4374c9e95c930a38de7adbd4323774798f4fe6ec6f24afcd6f2c7298ca44",
6033
+ "fabric-package-schema.mjs": "cd28092375db0fc21ffab1f0bb7794f7f8979ee08c64d3b9faf4b3845357caa6",
6034
+ "fabric-package.mjs": "8cfb32eebbd4e1bcf28a6e4437344ae2dd54479b0e7c820f002e9f94ab9ecaad",
6035
+ "fabric-protocols.mjs": "a560b7d6eb0d26204c5536711c3dda9daae90cc91e07cdc75412e75c86272767",
6036
+ "fabric-actions.mjs": "06e42f5e24c96311d5417d0d1effa93479ef7128a7ab139903b2bcf59253f6be",
6037
+ "fabric-connections.mjs": "303432e547ce563e90ca9ffcd827f5612f51d3582929834e1add0fdaf6485dcc",
6038
+ "fabric-a2a.mjs": "51b72fe1d80649d659fcad3a8f96370db3476c4a7b30cbabd8522c138be69346",
6039
+ "fabric-page-links.mjs": "a8834926e9d4bbf7c4857f551451d2ebf6ac8873bbccaaf89c5e30cf45b17ee6",
6040
+ "fabric-lock.mjs": "02cf833c97a07a8b3c788f9c93f70c4b9c9066efa25318dccf0038e0fc79717f",
6041
+ "fabric-usage.mjs": "1c4d18004639409624ac3516a02f2b60bbf55abdb612e9a96c37e83666eb87a7",
6042
+ "fabric-backups.mjs": "cfd8c9085e3d597a783099c2bd2ffe2f3faa0daaadab46dedd30523894cfeb06",
6043
+ "fabric-descriptor.mjs": "7c0ef7d245c037eb9e859ab481f6e66fb3e5ef2cf6d1e0a8d32b6d303097ca43",
6044
+ "fabric-context.mjs": "1112d695e872f9825cbc94f08484974bff3880087bc29b8be59f885f03e8f7be",
6045
+ "fabric-auth.mjs": "10ff37a39f9e3adb4d0f05db66c45f49b10eef582e9220c213907964109d7e52",
6046
+ "fabric-events.mjs": "c463d6ffcae24229a5c608d8fcea4268d2ccc5024b19fa10e5a452284068fa71",
6047
+ "fabric-logs.mjs": "58467e5719c16e099d05bbedec47a95712506ab03c33f3cd4be1252e8498a946",
6048
+ "fabric-supervisors.mjs": "e33b2b8916aeed617eee6233e05bd637bb4ecd87064248fd7ea08fdfcd45d375",
6049
+ "fabric-service.mjs": "297fef11ac76dc831d12d24c5581b7a93587c300c20664db703b3f924c0f9f1a",
6050
+ "fabric-profiles.mjs": "314376cf2deb87f235fb18b11d3b532e211f585b9af0a9302b5f4cc39971b532",
6051
+ "fabric-interop-rules.mjs": "b4e386c359a48e49ffff8a842215760c18a7c98a0af4754a808a35fb2820d458",
6052
+ "fabric-interop.mjs": "989040aed33b2712a258244192bdf70e811a51076aa1b62f2adc2a6db051dbed",
6053
+ "fabric-hub.mjs": "73ab07f72320a50042f39b52893b563157be2ac94615614416df45a796eac988",
6054
+ "fabric-board-shapes.mjs": "c1db7b7bd0d58d82bb6d8dfbc3cd1547a256a333052d367e82ff1b3edf2804d7",
6055
+ "fabric-board-link.mjs": "6e7d51f4fd9730d93455f50dd30e97907b8b9e1ca65a1d69f036f2e8ec05cc0d",
6056
+ "fabric-board-slots.mjs": "fc77a3c6e62aa18575568bef4f703cce2edaba8cef648813ebcdbb21bdc27a11",
6057
+ "fabric-board-session.mjs": "18555962e5f6d18080a3e7971c4c6640452542f6042d07917e7ebc073721c415",
6058
+ "fabric-board-fixture.mjs": "83c4b7e33ee47b68385faf2569d38d5c8a0c5cb0f8656090f41e1b0eed2f436e",
6059
+ "fabric-board.mjs": "15fbb4441fcf7d2f285375b75de64ad6cffea129c515084c110245376b07775f",
6060
+ "fabric-http.mjs": "b83b4c0c208763d56c3eebda5fe9e4a46d595cd91227699bf6876e65a3c7f9b9",
6061
+ "fabric-openrouter.mjs": "6041f3ab30f516658e1dbab4897a651cc8509b2136cfa8e769802c6b40ec2f35",
6062
+ "fabric-package.schema.json": "2ba799f576fad0f608029223c4ccccd122152f1c5dbfa8ce8b31cd63ac92ad44",
6063
+ "share-registration.schema.json": "34b3997eeaf936ebc861342a23045634a7c18c19f01d7ed4198310d81989f5b0"
5859
6064
  }
5860
6065
  },
5861
6066
  "data": {
@@ -5,9 +5,9 @@ license: AGPL-3.0-only OR LicenseRef-PassionCode-Commercial
5
5
  compatibility: Requires filesystem access and Python 3.9+. Exact schema checks additionally need git, Node.js, pnpm, and the pinned fabric-agent-contract checkout (a public repository). Works without those tools in an explicitly degraded structural-check mode. Ships in one plugin with adapting-projects-to-fabric, whose scripts it reuses.
6
6
  metadata:
7
7
  author: PassionCode.ai
8
- version: "0.73.0"
8
+ version: "0.75.0"
9
9
  contract-version: "0.1.0"
10
- contract-commit: "eac1a594aa131851f079da8bb7b2149e1951f35f"
10
+ contract-commit: "18f8d48762edc5bfb1433657cbfe1c16196df1a6"
11
11
  ---
12
12
 
13
13
  # Creating Fabric-compatible agents
@@ -61,10 +61,10 @@ No file is created until every row has an answer. An answer of "later" fails the
61
61
  | **Whose data does it keep?** | the kind of its data, named in the README: **U** when it keeps data of people outside the owner's team (messages, support requests, reviews, customers' answers), which never enters the source, a copy of it or its tests: the source holds the schema and synthetic fixtures, and a copy starts with an empty store of its own; **O** when it keeps none (a tool or service for other agents, the owner's reports, runs and media). In doubt, U. Either way the data lives in `<agent>-data` (a kit service: the kit's folders; on a cloud host: a durable store), apart from the source, from the first commit (references/source-and-instance.md) |
62
62
  | **Who holds the copyright?** | the holder the agent's `LICENSE` names: a new private agent (built for its owner or for a client) gets a `LICENSE` naming that holder in its first commit, all rights reserved unless the owner gives other terms; a public product keeps its own licence (a PassionCode.ai repository: the organization's, step 2) |
63
63
  | **Which models?** | per lane (planning, replies, volume work, media): a primary, a fallback of another vendor, an open-vendor model where it reads what users send, the input kinds each reads, declared as classes in the profile (references/models-and-providers.md) |
64
- | **Who pays?** | one key per agent and context with its own ceiling, from the estate's key manager, read from the environment; checked before every call; a personal key never pays for an organization |
64
+ | **Who pays?** | one key per agent and context with its own ceiling (USD 100 a month by default, more only where the operator names it), from the estate's key manager, read from the environment; checked before every call, the agent's own stop under the key's limit; a personal key never pays for an organization |
65
65
  | **How does it learn?** | decisions recorded with reasons, one trace per turn, every failure a planted fixture first, history replayed, learnings proposed and never self-approved (references/orchestration-and-learning.md) |
66
66
  | **Text for people?** | if it writes anything a person reads (a reply, a message, a post, a report, a UI string), its prompt forbids the em dash (U+2014) and any substitute for it, and a test fails on U+2014 in new output, from the first commit (the resilience reference, *Text for people*) |
67
- | **Does it answer people?** | if it answers people in a chat, by mail, in store reviews or in a group, it carries from its first release the turn record and the daily `support.quality_daily` report, the lane table with vendor exclusion and fallback recoveries counted, a writer change only after an offline replay, false-state gates and a checker that sees the material first, numbers and account state from tools, the live tail re-read before sending, repair then research then a hold that comes back, hand-offs by cause and never counted or judged as answers, a commitments ledger, a knowledge client that reads the service's `answer` flag, a gap queue and a feed re-read on a new event kind (references/agents-that-answer-people.md) |
67
+ | **Does it answer people?** | if it answers people in a chat, by mail, in store reviews or in a group, it starts from references/communication-agent-template.md and carries from its first release the turn record and the daily `support.quality_daily` report, the lane table with vendor exclusion and fallback recoveries counted, a writer change only after an offline replay, false-state gates and a checker that sees the material first, numbers and account state from tools, the live tail re-read before sending, repair then research then a hold that comes back, hand-offs by cause and never counted or judged as answers, a commitments ledger, a knowledge client that reads the service's `answer` flag, a gap queue and a feed re-read on a new event kind (references/agents-that-answer-people.md) |
68
68
 
69
69
  ## Step 1: the knowledge intake
70
70
 
@@ -101,6 +101,9 @@ prior art of its own:
101
101
  calling other agents, stops for a person, learning loops, the loop guard.
102
102
  - [agents-that-answer-people.md](references/agents-that-answer-people.md): what an agent that
103
103
  answers people carries from its first release, each part with the check that proves it.
104
+ - [communication-agent-template.md](references/communication-agent-template.md): the template prompt
105
+ for an agent that talks with people on a channel (support, sales and leads, community, inbox, reviews): the measured
106
+ inbound pipeline, business patterns, knowledge, the learning loop and acceptance.
104
107
 
105
108
  ## Step 2: the project skeleton
106
109
 
@@ -156,7 +159,7 @@ python3 <plugin-dir>/skills/adapting-projects-to-fabric/scripts/adapt_project.py
156
159
  The effect class is declared, never defaulted: ask the author what the agent does outside itself when the request
157
160
  does not say. Cost presets are only for a run whose cost varies; their amounts come from the author or measured runs.
158
161
 
159
- Pin exactly contract `0.1.0` at commit `eac1a594aa131851f079da8bb7b2149e1951f35f` and
162
+ Pin exactly contract `0.1.0` at commit `18f8d48762edc5bfb1433657cbfe1c16196df1a6` and
160
163
  read the pinned guide before implementing protocol details. If this skill is installed
161
164
  without its sibling, the scaffolder is absent: create the bundle by hand from the pinned
162
165
  contract's `docs/guides/connecting-compatible-agents.md` and mark the structural check
@@ -1,7 +1,8 @@
1
1
  # Agents that answer people: what they carry from the first release
2
2
 
3
3
  **Load this when the agent you are building answers people**: private chats, mail, store reviews, group chats, any
4
- channel where a person asks and the agent writes back. An agent on such a channel also follows the channel-agent
4
+ channel where a person asks and the agent writes back. Build it from the template prompt,
5
+ [communication-agent-template.md](communication-agent-template.md); this page holds the parts and their checks. An agent on such a channel also follows the channel-agent
5
6
  standard: [practices](practices.md#agents-on-a-channel-people-write-to). Every item below is a part of the agent, built and tested in its
6
7
  first release, not a later improvement. Each comes from the sources below: what the quality standard requires (A1,
7
8
  A5), and what an audit of five production agents found working or failing (P1 to P8). The practices are field
@@ -36,7 +37,10 @@ outage during the repair is a plain hand-off), and research and the hold stay th
36
37
 
37
38
  ## The record and the daily report
38
39
 
39
- - **Every inbound message is a turn with a trace id** (A1): the id is on the turn row, on each model call of that turn,
40
+ - **Every inbound message belongs to one turn with a trace id** (A1 counts each message as a turn; a burst the
41
+ communication agent template batches is one turn listing its message ids, so `turns` counts batched turns while
42
+ `replyCoverage` stays over inbound messages in chat and mail, over owed questions in community and reviews: each message of a turn whose reply was accepted counts as covered, and a message no
43
+ reply is owed to, such as a closing, an automated sender, spam or the staff's own, leaves the count); the id is on the turn row, on each model call of that turn,
40
44
  on its log line and on any copy a person reads. The turn stores its outcome (answered, general guidance, not covered,
41
45
  handed off, small talk, limit, error), the hand-off reason and category, the latency, the knowledge revision the
42
46
  answer used, and whether the channel accepted the reply. Conversation text stays inside the agent, redacted, for at