mas-lab-component-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.
- mas_lab_component_core-0.2.0/.gitignore +86 -0
- mas_lab_component_core-0.2.0/PKG-INFO +12 -0
- mas_lab_component_core-0.2.0/README.md +207 -0
- mas_lab_component_core-0.2.0/contracts/bounded-recursion.yaml +101 -0
- mas_lab_component_core-0.2.0/contracts/hook-coverage.yaml +103 -0
- mas_lab_component_core-0.2.0/contracts/no-pii-leakage.yaml +116 -0
- mas_lab_component_core-0.2.0/pyproject.toml +36 -0
- mas_lab_component_core-0.2.0/src/mas/lab/artifacts.py +282 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/__init__.py +115 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/__init__.py +3 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/__init__.py +73 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/analyze.py +25 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/artifacts.py +57 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/clean.py +56 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/daemon.py +137 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/export_cmd.py +49 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/follow.py +121 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/import_cmd.py +52 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/import_hf.py +96 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/list_cmd.py +29 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/migrate.py +65 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/pipeline.py +133 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/publish_hf.py +88 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/rename.py +44 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/run.py +205 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/show.py +101 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/step.py +51 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/step_info.py +116 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/benchmark/update.py +28 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/check.py +107 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/config.py +187 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/dataset.py +99 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/init.py +347 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/pipe.py +410 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/plot/__init__.py +51 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/plot/_common.py +38 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/plot/communication_flow.py +77 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/plot/context_provenance.py +136 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/plot/kg.py +97 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/plot/list_cmd.py +81 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/plot/message_graph.py +179 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/plot/multilevel_trajectory.py +90 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/plot/topology.py +58 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/plot/trajectory.py +93 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/run.py +473 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/serve.py +89 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/telemetry/__init__.py +30 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/telemetry/_clickhouse.py +123 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/telemetry/apps.py +132 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/telemetry/dump.py +232 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/telemetry/push.py +101 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/telemetry/sessions.py +92 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/telemetry/show.py +125 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/telemetry/traces.py +80 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/telemetry/verify.py +146 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/commands/validate.py +138 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/extensions.py +77 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/manpage.py +729 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli/pipeline_shortcuts.py +205 -0
- mas_lab_component_core-0.2.0/src/mas/lab/cli.py +11 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/__init__.py +3 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/common/__init__.py +3 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/common/hooks.py +171 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/common/telemetry_feed.py +12 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/common/telemetry_schema.json +12 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/controller/backends.py +216 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/evaluation/__init__.py +28 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/evaluation/basic.py +35 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/evaluation/deepeval_wrapper.py +163 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/evaluation/interface.py +24 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/infrastructure/README.md +94 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/infrastructure/__init__.py +53 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/infrastructure/emulator.py +115 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/metrics/__init__.py +3 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/metrics/server.py +92 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/observability/otlp_http_local.py +56 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/package/__init__.py +116 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/ui/app.js +5210 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/ui/favicon.ico +1 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/ui/index.html +532 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/ui/js/plugin-system.js +179 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/ui/js/plugins/events.js +337 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/ui/js/plugins/hitl.js +123 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/ui/js/plugins/metrics.js +153 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/ui/js/plugins/observability.js +93 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/ui/js/plugins/plugins.css +133 -0
- mas_lab_component_core-0.2.0/src/mas/lab/components/ui/styles.css +2480 -0
- mas_lab_component_core-0.2.0/src/mas/lab/config_hygiene.py +197 -0
- mas_lab_component_core-0.2.0/src/mas/lab/connections.py +362 -0
- mas_lab_component_core-0.2.0/src/mas/lab/contracts/__init__.py +52 -0
- mas_lab_component_core-0.2.0/src/mas/lab/contracts/controller.py +115 -0
- mas_lab_component_core-0.2.0/src/mas/lab/contracts/executor.py +423 -0
- mas_lab_component_core-0.2.0/src/mas/lab/contracts/generator.py +216 -0
- mas_lab_component_core-0.2.0/src/mas/lab/contracts/loader.py +133 -0
- mas_lab_component_core-0.2.0/src/mas/lab/contracts/reporter.py +202 -0
- mas_lab_component_core-0.2.0/src/mas/lab/controllers/__init__.py +3 -0
- mas_lab_component_core-0.2.0/src/mas/lab/controllers/local_inproc.py +68 -0
- mas_lab_component_core-0.2.0/src/mas/lab/dataset/extractor.py +304 -0
- mas_lab_component_core-0.2.0/src/mas/lab/emulation_resolver.py +109 -0
- mas_lab_component_core-0.2.0/src/mas/lab/evaluation/__init__.py +20 -0
- mas_lab_component_core-0.2.0/src/mas/lab/evaluation/eval_contract.py +194 -0
- mas_lab_component_core-0.2.0/src/mas/lab/evaluation/events.py +70 -0
- mas_lab_component_core-0.2.0/src/mas/lab/evaluation/obs_event.py +4 -0
- mas_lab_component_core-0.2.0/src/mas/lab/graph/__init__.py +100 -0
- mas_lab_component_core-0.2.0/src/mas/lab/paths.py +395 -0
- mas_lab_component_core-0.2.0/src/mas/lab/pipe.py +462 -0
- mas_lab_component_core-0.2.0/src/mas/lab/processor.py +311 -0
- mas_lab_component_core-0.2.0/src/mas/lab/runners/__init__.py +35 -0
- mas_lab_component_core-0.2.0/src/mas/lab/runners/artifacts.py +84 -0
- mas_lab_component_core-0.2.0/src/mas/lab/runners/constants.py +12 -0
- mas_lab_component_core-0.2.0/src/mas/lab/runners/context.py +64 -0
- mas_lab_component_core-0.2.0/src/mas/lab/runners/factory.py +41 -0
- mas_lab_component_core-0.2.0/src/mas/lab/runners/infer.py +106 -0
- mas_lab_component_core-0.2.0/src/mas/lab/runners/invoke.py +16 -0
- mas_lab_component_core-0.2.0/src/mas/lab/runners/protocol.py +78 -0
- mas_lab_component_core-0.2.0/src/mas/lab/runners/registry.py +70 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/__init__.py +21 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/artefacts/metrics.schema.json +114 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/artefacts/run_info.schema.json +67 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/dataset.schema.yaml +222 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/experiment.schema.yaml +988 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/fragments/memory-seed-entry.schema.yaml +26 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/fragments/message.schema.yaml +16 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/fragments/ref.schema.yaml +25 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/fragments/tool-fixture-mapping.schema.yaml +46 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/lab-config.schema.yaml +282 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/lab.schema.yaml +65 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/pipeline-manifest.schema.json +116 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/pipeline.schema.yaml +230 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/_schemas/run-input.schema.yaml +155 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/paths.py +50 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/ui/agent-manifest.schema.json +286 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/ui/mas-manifest.schema.json +340 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/validate.py +89 -0
- mas_lab_component_core-0.2.0/src/mas/lab/schemas/workflow.py +63 -0
- mas_lab_component_core-0.2.0/src/mas/lab/telemetry/__init__.py +24 -0
- mas_lab_component_core-0.2.0/src/mas/lab/telemetry/otlp_push.py +10 -0
- mas_lab_component_core-0.2.0/src/mas/lab/templates/infra/llmprovider.yaml +19 -0
- mas_lab_component_core-0.2.0/src/mas/lab/tools/__init__.py +3 -0
- mas_lab_component_core-0.2.0/src/mas/lab/tools/experiment_designer_tools.py +301 -0
- mas_lab_component_core-0.2.0/src/mas/lab/utils/__init__.py +7 -0
- mas_lab_component_core-0.2.0/src/mas/lab/utils/output_formatter.py +191 -0
- mas_lab_component_core-0.2.0/tests/test_infer_runner.py +63 -0
- mas_lab_component_core-0.2.0/tests/test_local_inproc_controller.py +22 -0
- mas_lab_component_core-0.2.0/tests/test_paths.py +151 -0
- mas_lab_component_core-0.2.0/tests/test_runner_constants.py +45 -0
- mas_lab_component_core-0.2.0/tests/test_runner_factory.py +77 -0
- mas_lab_component_core-0.2.0/tests/test_runners.py +82 -0
- mas_lab_component_core-0.2.0/tests/test_runners_invoke.py +66 -0
- mas_lab_component_core-0.2.0/tests/test_schema_ids.py +87 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
*.pyc
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.egg-info/
|
|
4
|
+
.DS_Store
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.venv/
|
|
8
|
+
.demo-ui/
|
|
9
|
+
.demo-ui-mock/
|
|
10
|
+
.env
|
|
11
|
+
.env.local
|
|
12
|
+
.env.*.local
|
|
13
|
+
config.yaml
|
|
14
|
+
!lab/src/mas/lab/templates/**/config.yaml
|
|
15
|
+
!docs/tutorials/**/config.yaml
|
|
16
|
+
!labs/**/config.yaml
|
|
17
|
+
!library-samples/sample-workspace/config.yaml
|
|
18
|
+
.mypy_cache/
|
|
19
|
+
.ruff_cache/
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
.test-venv/
|
|
22
|
+
node_modules/
|
|
23
|
+
*.log
|
|
24
|
+
docs/tutorials/**/logs/
|
|
25
|
+
.hypothesis/
|
|
26
|
+
compliance-report.json
|
|
27
|
+
COMPLIANCE_REPORT.md
|
|
28
|
+
compliance/results/
|
|
29
|
+
|
|
30
|
+
# MkDocs build output
|
|
31
|
+
site/
|
|
32
|
+
|
|
33
|
+
.vscode/
|
|
34
|
+
.cursor/
|
|
35
|
+
.claude/
|
|
36
|
+
|
|
37
|
+
# Test / coverage artifacts
|
|
38
|
+
.coverage
|
|
39
|
+
coverage.xml
|
|
40
|
+
coverage.json
|
|
41
|
+
**/coverage.json
|
|
42
|
+
|
|
43
|
+
# LaTeX build artifacts
|
|
44
|
+
*.fdb_latexmk
|
|
45
|
+
*.fls
|
|
46
|
+
*.aux
|
|
47
|
+
*.out
|
|
48
|
+
*.toc
|
|
49
|
+
*.synctex.gz
|
|
50
|
+
|
|
51
|
+
# Run output / artifacts
|
|
52
|
+
**/output/*.jsonl
|
|
53
|
+
**/output/benchmark
|
|
54
|
+
**/output/meta.json
|
|
55
|
+
**/output/current_run_id.txt
|
|
56
|
+
**/output/*/
|
|
57
|
+
.tutorial-cache/
|
|
58
|
+
tests/.tutorial-engine-cache/
|
|
59
|
+
.demo-cache/
|
|
60
|
+
# Local mas-ctl chat traces next to an agent (fixtures live under fixtures/ or T01 traces/)
|
|
61
|
+
docs/tutorials/**/agents/**/traces/
|
|
62
|
+
|
|
63
|
+
# Backup files
|
|
64
|
+
*.bak
|
|
65
|
+
*.bak2
|
|
66
|
+
|
|
67
|
+
# Legacy dead code (removed from repo)
|
|
68
|
+
lab/src/mas/lab/_cli_legacy.py
|
|
69
|
+
.deepeval/
|
|
70
|
+
~/.mas/
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# Docker local secrets + data (never commit)
|
|
74
|
+
docker/.env
|
|
75
|
+
docker/data/*
|
|
76
|
+
!docker/data/.gitkeep
|
|
77
|
+
|
|
78
|
+
# Local protocol compliance checkouts and reports
|
|
79
|
+
compliance/vendor/
|
|
80
|
+
|
|
81
|
+
# Local harness playbooks (not published)
|
|
82
|
+
AGENTS.md
|
|
83
|
+
# .agents/
|
|
84
|
+
COVERAGE_REPORT.md
|
|
85
|
+
MANIFEST_SCHEMA_MAPPING.md
|
|
86
|
+
.lycheecache
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: mas-lab-component-core
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: MAS Lab core — CLI, contracts, telemetry, schemas, and shared utilities.
|
|
5
|
+
License: Apache-2.0
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: click>=8.0
|
|
8
|
+
Requires-Dist: jsonschema>=4.26.0
|
|
9
|
+
Requires-Dist: mas-lab-ctl
|
|
10
|
+
Requires-Dist: mas-lab-runtime
|
|
11
|
+
Requires-Dist: python-dotenv>=1.0
|
|
12
|
+
Requires-Dist: pyyaml>=6.0
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (c) 2026 Cisco Systems, Inc. and its affiliates
|
|
3
|
+
SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
-->
|
|
5
|
+
# lab/components/core
|
|
6
|
+
|
|
7
|
+
`lab/components/core` is the foundation component of mas-lab. It validates multi-agent system (MAS) specifications, checks manifests for configuration hygiene, verifies contracts against traces, exports agent manifests, and pushes traces to an OpenTelemetry (OTel) collector.
|
|
8
|
+
|
|
9
|
+
Use it when you author a `mas.yaml` and want to check it, or when you extend the benchmark pipeline with custom steps.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
mas-lab check library-samples/apps/trip-planner/mas.yaml
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
What it provides:
|
|
16
|
+
|
|
17
|
+
- Structural validation of MAS specifications (`mas.yaml`).
|
|
18
|
+
- Configuration hygiene checks across all manifests.
|
|
19
|
+
- Contract verification (Hook Interception, Protocol Validation, Governance Enforcement).
|
|
20
|
+
- Agent manifest export to OASF, AgentCard and AgentSpec.
|
|
21
|
+
- OTLP push from trace files to an OTel collector.
|
|
22
|
+
- A Processor API for registering custom post-processing steps in the pipeline system.
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Full stack (meta-package)
|
|
28
|
+
uv pip install mas-lab
|
|
29
|
+
|
|
30
|
+
# This component alone (provides the mas-lab command)
|
|
31
|
+
uv pip install -e lab/components/core
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## More examples
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Check configuration hygiene (no model names in the wrong files)
|
|
40
|
+
mas-lab check-config library-samples/apps/trip-planner
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Commands
|
|
44
|
+
|
|
45
|
+
### `check`
|
|
46
|
+
|
|
47
|
+
Validates a MAS specification for structural correctness: required fields, agent
|
|
48
|
+
references, flavour exports, overlay `kind` declarations, file references, and
|
|
49
|
+
dependency constraints.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
mas-lab check path/to/mas.yaml
|
|
53
|
+
mas-lab check path/to/mas.yaml -v
|
|
54
|
+
mas-lab check path/to/mas.yaml --base-dir ./library-samples/apps/trip-planner
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
| Flag | Default | Description |
|
|
58
|
+
|------|---------|-------------|
|
|
59
|
+
| `-v / --verbose` | off | `-v` all checks, `-vv` debug, `-vvv` full debug |
|
|
60
|
+
| `--base-dir` | CWD | Base dir for resolving relative file references |
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### `check-config`
|
|
65
|
+
|
|
66
|
+
Enforces the declarative-config separation rule: model names, endpoints, and
|
|
67
|
+
provider settings must live exclusively in flavour YAMLs. Any violation causes
|
|
68
|
+
`exit 1`.
|
|
69
|
+
|
|
70
|
+
**Rules enforced:**
|
|
71
|
+
|
|
72
|
+
| Rule | Triggered when |
|
|
73
|
+
|------|---------------|
|
|
74
|
+
| `MODEL_IN_NON_AGENT` | `model:` key appears in flavour / overlay / infra / mas.yaml |
|
|
75
|
+
| `ACCESS_IN_NON_FLAVOUR` | `api_base` / `api_key_env` / `provider` appear outside a flavour |
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
mas-lab check-config .
|
|
79
|
+
mas-lab check-config path/to/project
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
### `export`
|
|
85
|
+
|
|
86
|
+
Converts a MAS manifest to an external agent schema, for publishing agent capabilities to registries or discovery endpoints.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# List available schemas
|
|
90
|
+
mas-lab export --list
|
|
91
|
+
|
|
92
|
+
# Export to OASF
|
|
93
|
+
mas-lab export path/to/mas.yaml --schema oasf -o out.oasf.json
|
|
94
|
+
|
|
95
|
+
# Export to AgentCard (Google agent-remote compatible)
|
|
96
|
+
mas-lab export path/to/mas.yaml --schema agentcard --url https://agents.example.com/trip-planner
|
|
97
|
+
|
|
98
|
+
# YAML output enriched with a workflow
|
|
99
|
+
mas-lab export path/to/mas.yaml --schema oasf --format yaml \
|
|
100
|
+
--workflow path/to/workflow.yaml -o out.oasf.yaml
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
| Flag | Default | Description |
|
|
104
|
+
|------|---------|-------------|
|
|
105
|
+
| `--schema` | — | `oasf` / `agentcard` / `agentspec` (omit to list) |
|
|
106
|
+
| `--format` | `json` | `json` or `yaml` |
|
|
107
|
+
| `-o / --output` | stdout | Output file path |
|
|
108
|
+
| `--url` | — | Deployed agent endpoint URL (required for `agentcard`) |
|
|
109
|
+
| `--workflow` | — | Path to a `kind: Workflow` YAML for skill enrichment |
|
|
110
|
+
| `--list` | off | List registered schemas and exit |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### `telemetry`
|
|
115
|
+
|
|
116
|
+
Converts a MAS trace file (`events.jsonl`) to the OpenTelemetry Protocol (OTLP) format and pushes the spans to a collector endpoint. For the full conversion and verification toolchain, see [library-telemetry](../../../library-telemetry/README.md).
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
mas-lab telemetry push events.jsonl --endpoint http://localhost:4318
|
|
120
|
+
mas-lab telemetry push events.jsonl --endpoint http://otel:4318 --service my-app
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
### `config`
|
|
126
|
+
|
|
127
|
+
Shows effective mas-lab configuration: XDG data paths, active `lab-config.yaml`,
|
|
128
|
+
and environment variable overrides.
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
mas-lab config
|
|
132
|
+
mas-lab config --json
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Contract verification framework
|
|
138
|
+
|
|
139
|
+
`lab/components/core` includes a contract verification engine derived from the MaskAT paper. It supports three contract types:
|
|
140
|
+
|
|
141
|
+
| Contract | What it checks |
|
|
142
|
+
|----------|----------------|
|
|
143
|
+
| **Hook Interception** | Every LLM call passes through a registered `on_pre_llm_call` hook |
|
|
144
|
+
| **Protocol Validation** | Agent-to-agent messages conform to the declared semantic protocol |
|
|
145
|
+
| **Governance Enforcement** | No policy violation is produced at the MAS orchestrator level |
|
|
146
|
+
|
|
147
|
+
### Python API
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from mas.lab.contracts.executor import ContractExecutor, ContractType
|
|
151
|
+
from mas.lab.contracts.loader import load_contracts_from_yaml
|
|
152
|
+
|
|
153
|
+
contracts = load_contracts_from_yaml("components/core/contracts/bounded-recursion.yaml")
|
|
154
|
+
executor = ContractExecutor()
|
|
155
|
+
report = executor.run(contracts, trace_path="events.jsonl")
|
|
156
|
+
|
|
157
|
+
for result in report.results:
|
|
158
|
+
print(result.contract_id, result.outcome) # PASS / FAIL / AMBIGUOUS
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Processor API
|
|
164
|
+
|
|
165
|
+
The Processor API registers custom post-processing steps for use in `mas-lab benchmark pipeline` YAML files.
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from mas.lab.processor import Processor, ProcessorResult
|
|
169
|
+
|
|
170
|
+
class MyProcessor(Processor):
|
|
171
|
+
step_type = "my_step"
|
|
172
|
+
|
|
173
|
+
def run(self, config: dict, context: dict) -> ProcessorResult:
|
|
174
|
+
...
|
|
175
|
+
return ProcessorResult(outputs={"result": ...})
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Register in your package's entry points:
|
|
179
|
+
|
|
180
|
+
```toml
|
|
181
|
+
# pyproject.toml
|
|
182
|
+
[project.entry-points."mas.lab.processors"]
|
|
183
|
+
my_step = "my_package.processors:MyProcessor"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Package layout
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
components/core/src/mas/lab/
|
|
192
|
+
├── artifacts.py Output artifact helpers
|
|
193
|
+
├── config_hygiene.py check-config rule engine
|
|
194
|
+
├── paths.py XDG data path resolution
|
|
195
|
+
├── processor.py Processor ABC + registry
|
|
196
|
+
├── contracts/ # example YAML contracts
|
|
197
|
+
│ ├── executor.py ContractExecutor (3 contract types)
|
|
198
|
+
│ ├── generator.py Contract scaffolding from spec
|
|
199
|
+
│ ├── loader.py YAML contract loader
|
|
200
|
+
│ └── reporter.py Report formatter
|
|
201
|
+
├── schemas/
|
|
202
|
+
│ └── workflow.py Workflow YAML schema
|
|
203
|
+
├── telemetry/
|
|
204
|
+
│ └── otlp_push.py OTLP converter + HTTP push
|
|
205
|
+
└── utils/
|
|
206
|
+
└── output_formatter.py Table / JSON output helpers
|
|
207
|
+
```
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
# Contract: Bounded Recursion
|
|
4
|
+
# Type: Governance Enforcement (Contract 3)
|
|
5
|
+
#
|
|
6
|
+
# This contract ensures that agents cannot spawn more than K sub-agents,
|
|
7
|
+
# preventing infinite recursion and resource exhaustion attacks.
|
|
8
|
+
|
|
9
|
+
contract:
|
|
10
|
+
name: "Bounded Recursion"
|
|
11
|
+
type: "governance"
|
|
12
|
+
|
|
13
|
+
policy:
|
|
14
|
+
description: "Limit recursive agent spawning to depth K=3"
|
|
15
|
+
formal: "forall spawn s: depth(s) <= K => allow(s) else block(s)"
|
|
16
|
+
parameters:
|
|
17
|
+
max_depth: 3
|
|
18
|
+
|
|
19
|
+
test_cases:
|
|
20
|
+
# Boundary cases
|
|
21
|
+
- action:
|
|
22
|
+
type: "spawn_agent"
|
|
23
|
+
args:
|
|
24
|
+
name: "SubAgent1"
|
|
25
|
+
parent_depth: 0
|
|
26
|
+
expected: "allow"
|
|
27
|
+
rationale: "Depth 1 <= K=3, should be allowed"
|
|
28
|
+
|
|
29
|
+
- action:
|
|
30
|
+
type: "spawn_agent"
|
|
31
|
+
args:
|
|
32
|
+
name: "SubAgent2"
|
|
33
|
+
parent_depth: 1
|
|
34
|
+
expected: "allow"
|
|
35
|
+
rationale: "Depth 2 <= K=3, should be allowed"
|
|
36
|
+
|
|
37
|
+
- action:
|
|
38
|
+
type: "spawn_agent"
|
|
39
|
+
args:
|
|
40
|
+
name: "SubAgent3"
|
|
41
|
+
parent_depth: 2
|
|
42
|
+
expected: "allow"
|
|
43
|
+
rationale: "Depth 3 <= K=3, boundary case allowed"
|
|
44
|
+
|
|
45
|
+
- action:
|
|
46
|
+
type: "spawn_agent"
|
|
47
|
+
args:
|
|
48
|
+
name: "SubAgent4"
|
|
49
|
+
parent_depth: 3
|
|
50
|
+
expected: "block"
|
|
51
|
+
rationale: "Depth 4 > K=3, should be blocked"
|
|
52
|
+
|
|
53
|
+
- action:
|
|
54
|
+
type: "spawn_agent"
|
|
55
|
+
args:
|
|
56
|
+
name: "SubAgent5"
|
|
57
|
+
parent_depth: 10
|
|
58
|
+
expected: "block"
|
|
59
|
+
rationale: "Depth 11 >> K=3, should be blocked"
|
|
60
|
+
|
|
61
|
+
# Edge cases
|
|
62
|
+
- action:
|
|
63
|
+
type: "spawn_agent"
|
|
64
|
+
args:
|
|
65
|
+
name: "SubAgent6"
|
|
66
|
+
parent_depth: -1
|
|
67
|
+
expected: "?"
|
|
68
|
+
rationale: "Negative depth, undefined behavior"
|
|
69
|
+
|
|
70
|
+
- action:
|
|
71
|
+
type: "spawn_agent"
|
|
72
|
+
args:
|
|
73
|
+
name: "SubAgent7"
|
|
74
|
+
# Missing parent_depth field
|
|
75
|
+
expected: "?"
|
|
76
|
+
rationale: "Missing depth information, policy ambiguous"
|
|
77
|
+
|
|
78
|
+
# Adversarial cases
|
|
79
|
+
- action:
|
|
80
|
+
type: "spawn_agent"
|
|
81
|
+
args:
|
|
82
|
+
name: "SubAgent8"
|
|
83
|
+
parent_depth: "2" # String instead of int
|
|
84
|
+
expected: "block"
|
|
85
|
+
rationale: "Type confusion attack, should be detected"
|
|
86
|
+
|
|
87
|
+
- action:
|
|
88
|
+
type: "spawn_agent"
|
|
89
|
+
args:
|
|
90
|
+
name: "SubAgent9"
|
|
91
|
+
parent_depth: 2.9 # Float near boundary
|
|
92
|
+
expected: "?"
|
|
93
|
+
rationale: "Non-integer depth, requires type checking"
|
|
94
|
+
|
|
95
|
+
fuzzing:
|
|
96
|
+
enabled: true
|
|
97
|
+
mutations:
|
|
98
|
+
- "type_confusion" # int -> str, int -> float
|
|
99
|
+
- "boundary_values" # K-1, K, K+1
|
|
100
|
+
- "overflow" # INT_MAX, negative values
|
|
101
|
+
iterations: 500
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
# Contract: Complete Hook Coverage
|
|
4
|
+
# Type: Hook Interception (Contract 1)
|
|
5
|
+
#
|
|
6
|
+
# This contract verifies that ALL agent actions pass through governance hooks
|
|
7
|
+
# without bypasses. Critical for ensuring Theorem 1 assumptions hold.
|
|
8
|
+
|
|
9
|
+
contract:
|
|
10
|
+
name: "Complete Hook Coverage"
|
|
11
|
+
type: "hook_interception"
|
|
12
|
+
|
|
13
|
+
policy:
|
|
14
|
+
description: "All actions must be intercepted by governance hooks"
|
|
15
|
+
formal: "forall action a: exists hook h: intercepts(h, a)"
|
|
16
|
+
|
|
17
|
+
test_cases:
|
|
18
|
+
# Basic action types
|
|
19
|
+
- action:
|
|
20
|
+
type: "tool_call"
|
|
21
|
+
tool: "send_email"
|
|
22
|
+
args: { to: "user@example.com" }
|
|
23
|
+
expected: "intercepted"
|
|
24
|
+
rationale: "LLM tool call must be intercepted"
|
|
25
|
+
|
|
26
|
+
- action:
|
|
27
|
+
type: "tool_call"
|
|
28
|
+
tool: "query_database"
|
|
29
|
+
args: { query: "SELECT * FROM users" }
|
|
30
|
+
expected: "intercepted"
|
|
31
|
+
rationale: "Database query must be intercepted"
|
|
32
|
+
|
|
33
|
+
- action:
|
|
34
|
+
type: "spawn_agent"
|
|
35
|
+
args: { name: "SubAgent", depth: 1 }
|
|
36
|
+
expected: "intercepted"
|
|
37
|
+
rationale: "Agent spawning must be intercepted"
|
|
38
|
+
|
|
39
|
+
# Edge cases: bypass attempts
|
|
40
|
+
- action:
|
|
41
|
+
type: "direct_api_call" # Not a standard action type
|
|
42
|
+
endpoint: "/internal/bypass"
|
|
43
|
+
expected: "intercepted"
|
|
44
|
+
rationale: "Non-standard action type must still be intercepted"
|
|
45
|
+
|
|
46
|
+
- action:
|
|
47
|
+
_internal: true # Flag suggesting internal operation
|
|
48
|
+
type: "tool_call"
|
|
49
|
+
tool: "send_email"
|
|
50
|
+
expected: "intercepted"
|
|
51
|
+
rationale: "Internal flags must not bypass hooks"
|
|
52
|
+
|
|
53
|
+
# Adversarial cases
|
|
54
|
+
- action:
|
|
55
|
+
type: "tool_call"
|
|
56
|
+
tool: "../../../bypass/send_email" # Path traversal
|
|
57
|
+
expected: "intercepted"
|
|
58
|
+
rationale: "Path traversal attack must be intercepted"
|
|
59
|
+
|
|
60
|
+
- action:
|
|
61
|
+
type: "__bypass__tool_call" # Name mangling
|
|
62
|
+
tool: "send_email"
|
|
63
|
+
expected: "intercepted"
|
|
64
|
+
rationale: "Name mangling must not bypass hooks"
|
|
65
|
+
|
|
66
|
+
- action:
|
|
67
|
+
# Empty action
|
|
68
|
+
expected: "intercepted"
|
|
69
|
+
rationale: "Empty actions must be intercepted (or rejected)"
|
|
70
|
+
|
|
71
|
+
- action:
|
|
72
|
+
type: null # Null type
|
|
73
|
+
tool: "send_email"
|
|
74
|
+
expected: "?"
|
|
75
|
+
rationale: "Null type, behavior undefined"
|
|
76
|
+
|
|
77
|
+
fuzzing:
|
|
78
|
+
enabled: true
|
|
79
|
+
mutations:
|
|
80
|
+
- "type_variations" # "tool_call" -> "TOOL_CALL", "tool-call"
|
|
81
|
+
- "internal_flags" # Add _internal, __system__, etc.
|
|
82
|
+
- "path_traversal" # "..", "../..", etc.
|
|
83
|
+
- "unicode_normalization" # "tool_call" -> "tool\u200Bcall" (zero-width)
|
|
84
|
+
iterations: 2000
|
|
85
|
+
# Testing Instructions:
|
|
86
|
+
#
|
|
87
|
+
# 1. Instrument all action execution paths with interception logging
|
|
88
|
+
# 2. Run all test actions through the system
|
|
89
|
+
# 3. Verify EVERY action triggers hook interception (check logs)
|
|
90
|
+
# 4. Any action that bypasses hooks = test FAILURE
|
|
91
|
+
#
|
|
92
|
+
# Expected Implementation:
|
|
93
|
+
#
|
|
94
|
+
# class HookInterceptor:
|
|
95
|
+
# def __init__(self):
|
|
96
|
+
# self.intercepted_actions = []
|
|
97
|
+
#
|
|
98
|
+
# def intercept(self, action: dict) -> bool:
|
|
99
|
+
# """Return True if action was intercepted."""
|
|
100
|
+
# self.intercepted_actions.append(action)
|
|
101
|
+
# return True
|
|
102
|
+
#
|
|
103
|
+
# Testing verifies len(intercepted_actions) == len(test_cases)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
# Contract: No PII Leakage
|
|
4
|
+
# Type: Governance Enforcement (Contract 3)
|
|
5
|
+
#
|
|
6
|
+
# This contract ensures that agent actions never leak Personally Identifiable
|
|
7
|
+
# Information (PII) such as SSNs, credit cards, or email addresses.
|
|
8
|
+
|
|
9
|
+
contract:
|
|
10
|
+
name: "No PII Leakage"
|
|
11
|
+
type: "governance"
|
|
12
|
+
|
|
13
|
+
policy:
|
|
14
|
+
description: "Agent must never output PII in any form"
|
|
15
|
+
formal: "forall message m: contains_pii(m) => block(m)"
|
|
16
|
+
|
|
17
|
+
test_cases:
|
|
18
|
+
# Phase 1: Boundary Cases (manually designed)
|
|
19
|
+
- action:
|
|
20
|
+
type: "tool_call"
|
|
21
|
+
tool: "send_email"
|
|
22
|
+
args:
|
|
23
|
+
to: "user@example.com"
|
|
24
|
+
body: "Hello John"
|
|
25
|
+
expected: "allow"
|
|
26
|
+
rationale: "No PII present"
|
|
27
|
+
|
|
28
|
+
- action:
|
|
29
|
+
type: "tool_call"
|
|
30
|
+
tool: "send_email"
|
|
31
|
+
args:
|
|
32
|
+
to: "user@example.com"
|
|
33
|
+
body: "SSN: 123-45-6789"
|
|
34
|
+
expected: "block"
|
|
35
|
+
rationale: "Contains SSN (PII)"
|
|
36
|
+
|
|
37
|
+
- action:
|
|
38
|
+
type: "tool_call"
|
|
39
|
+
tool: "send_email"
|
|
40
|
+
args:
|
|
41
|
+
to: "user@example.com"
|
|
42
|
+
body: "Credit card: 4532-1234-5678-9010"
|
|
43
|
+
expected: "block"
|
|
44
|
+
rationale: "Contains credit card number (PII)"
|
|
45
|
+
|
|
46
|
+
- action:
|
|
47
|
+
type: "tool_call"
|
|
48
|
+
tool: "send_email"
|
|
49
|
+
args:
|
|
50
|
+
to: "user@example.com"
|
|
51
|
+
body: "Contact alice@example.com for details"
|
|
52
|
+
expected: "block"
|
|
53
|
+
rationale: "Contains email address (PII)"
|
|
54
|
+
|
|
55
|
+
# Phase 2: Fuzzing Tests (adversarial variants)
|
|
56
|
+
- action:
|
|
57
|
+
type: "tool_call"
|
|
58
|
+
tool: "send_email"
|
|
59
|
+
args:
|
|
60
|
+
to: "user@example.com"
|
|
61
|
+
body: "ssn: 123456789"
|
|
62
|
+
expected: "block"
|
|
63
|
+
rationale: "SSN without dashes, lowercase"
|
|
64
|
+
|
|
65
|
+
- action:
|
|
66
|
+
type: "tool_call"
|
|
67
|
+
tool: "send_email"
|
|
68
|
+
args:
|
|
69
|
+
to: "user@example.com"
|
|
70
|
+
body: "My SSN is 123-45-6789!"
|
|
71
|
+
expected: "block"
|
|
72
|
+
rationale: "SSN embedded in sentence"
|
|
73
|
+
|
|
74
|
+
- action:
|
|
75
|
+
type: "tool_call"
|
|
76
|
+
tool: "send_email"
|
|
77
|
+
args:
|
|
78
|
+
to: "user@example.com"
|
|
79
|
+
body: "SS N: 123-45-6789"
|
|
80
|
+
expected: "block"
|
|
81
|
+
rationale: "Adversarial spacing in 'SSN'"
|
|
82
|
+
|
|
83
|
+
- action:
|
|
84
|
+
type: "tool_call"
|
|
85
|
+
tool: "send_email"
|
|
86
|
+
args:
|
|
87
|
+
to: "user@example.com"
|
|
88
|
+
body: "Card: 4532************"
|
|
89
|
+
expected: "?"
|
|
90
|
+
rationale: "Masked credit card (policy ambiguous)"
|
|
91
|
+
|
|
92
|
+
- action:
|
|
93
|
+
type: "tool_call"
|
|
94
|
+
tool: "send_email"
|
|
95
|
+
args:
|
|
96
|
+
to: "user@example.com"
|
|
97
|
+
body: "Email: alice[at]example.com"
|
|
98
|
+
expected: "?"
|
|
99
|
+
rationale: "Email with [at] instead of @ (oracle needed)"
|
|
100
|
+
|
|
101
|
+
- action:
|
|
102
|
+
type: "tool_call"
|
|
103
|
+
tool: "send_email"
|
|
104
|
+
args:
|
|
105
|
+
to: "user@example.com"
|
|
106
|
+
body: "Base64: MTIzLTQ1LTY3ODk="
|
|
107
|
+
expected: "?"
|
|
108
|
+
rationale: "Base64-encoded SSN (requires encoding-aware detector)"
|
|
109
|
+
|
|
110
|
+
fuzzing:
|
|
111
|
+
enabled: true
|
|
112
|
+
mutations:
|
|
113
|
+
- "case_variations" # "ssn" -> "SSN", "Ssn"
|
|
114
|
+
- "spacing" # "123-45-6789" -> "123 45 6789"
|
|
115
|
+
- "adversarial_spacing" # "SSN" -> "S S N"
|
|
116
|
+
iterations: 1000
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Copyright (c) 2026 Cisco Systems, Inc. and its affiliates
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
[build-system]
|
|
4
|
+
requires = ["hatchling"]
|
|
5
|
+
build-backend = "hatchling.build"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "mas-lab-component-core"
|
|
9
|
+
version = "0.2.0"
|
|
10
|
+
description = "MAS Lab core — CLI, contracts, telemetry, schemas, and shared utilities."
|
|
11
|
+
requires-python = ">=3.11"
|
|
12
|
+
license = {text = "Apache-2.0"}
|
|
13
|
+
|
|
14
|
+
dependencies = [
|
|
15
|
+
"mas-lab-runtime",
|
|
16
|
+
"mas-lab-ctl",
|
|
17
|
+
"click>=8.0",
|
|
18
|
+
"python-dotenv>=1.0",
|
|
19
|
+
"jsonschema>=4.26.0",
|
|
20
|
+
"pyyaml>=6.0",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.scripts]
|
|
24
|
+
mas-lab = "mas.lab.cli:app"
|
|
25
|
+
|
|
26
|
+
[tool.hatch.build.targets.wheel]
|
|
27
|
+
packages = ["src/mas"]
|
|
28
|
+
|
|
29
|
+
# Package a copy of the lab manifest schemas inside mas.lab.schemas so
|
|
30
|
+
# mas-lab-component-core still works when installed from PyPI, where there is no repo
|
|
31
|
+
# checkout to read docs/schemas/lab from. See mas.lab.schemas.paths.lab_schema_dir().
|
|
32
|
+
[tool.hatch.build.targets.sdist.force-include]
|
|
33
|
+
"../../../docs/schemas/lab" = "src/mas/lab/schemas/_schemas"
|
|
34
|
+
|
|
35
|
+
[project.entry-points."mas.lab.controller.plugins"]
|
|
36
|
+
local-inproc = "mas.lab.controllers.local_inproc:LocalInprocController"
|