Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,19 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
- name: Install core (3.9)
if: matrix.python-version == '3.9'
run: pip install -e ".[dev]"
- name: Install core + adapter extras (3.10+)
if: matrix.python-version != '3.9'
run: pip install -e ".[dev,claude,openai,langchain]"
- name: Lint
run: python -m ruff check src/ tests/
- name: Type check
run: python -m mypy src/agent_contracts
- name: Test
run: python -m pytest --cov=agent_contracts --cov-report=term-missing
- name: Validate canonical contracts
run: |
python -m agent_contracts.cli validate AGENT_CONTRACT.yaml
python -m agent_contracts.cli validate examples/support_triage.yaml
53 changes: 49 additions & 4 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,69 @@
name: Publish to PyPI
name: Release

on:
release:
types: [published]
push:
tags:
- "v*"

permissions:
contents: write
id-token: write

concurrency: ${{ github.workflow }}-${{ github.ref }}

jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check repository hygiene
run: |
if git ls-files | rg -n '(^|/)(AGENTS\.md|CLAUDE\.md|docs/plans/|\.omx/|\.pilot/|\.dev-session/|\.staff-engineer-state\.json|\.staff-engineer\.json|ROADMAP\.md)$'; then
echo "Tracked internal-only files found in public release tree."
exit 1
fi
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Check tag version
run: |
TAG_VERSION="${GITHUB_REF_NAME#v}"
PKG_VERSION="$(python -c "from pathlib import Path; ns = {}; exec(Path('src/agent_contracts/_version.py').read_text(encoding='utf-8'), ns); print(ns['__version__'])")"
test "$TAG_VERSION" = "$PKG_VERSION"
- name: Install dependencies
run: python -m pip install -e ".[dev]" build twine
- name: Lint
run: python -m ruff check src/ tests/
- name: Type check
run: python -m mypy src/agent_contracts
- name: Test
run: python -m pytest --cov=agent_contracts --cov-report=term-missing
- name: Validate canonical contracts
run: |
python -m agent_contracts.cli validate AGENT_CONTRACT.yaml
python -m agent_contracts.cli validate examples/support_triage.yaml
python -m agent_contracts.cli check-compat examples/support_triage.yaml examples/support_triage.yaml
- name: Build package
run: python -m build
- name: Check distributions
run: python -m twine check dist/*

publish:
runs-on: ubuntu-latest
needs: verify
environment: pypi
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install build tools
run: pip install build
run: python -m pip install build
- name: Build package
run: python -m build
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ htmlcov/
.coverage
.coverage.*
*.lcov
.omx/
.pilot/
.dev-session/
.staff-engineer-state.json
AGENTS.md
CLAUDE.md
docs/plans/
ROADMAP.md
231 changes: 33 additions & 198 deletions AGENT_CONTRACT.yaml
Original file line number Diff line number Diff line change
@@ -1,219 +1,54 @@
# Tier 2 — Composable Contract (Full Reference Example)
# Supports multi-agent DAG composition, canary analysis, rollback,
# and regulatory audit trails.
# Canonical coding/build repo contract

agent_contract: "0.1.0"

identity:
name: support-triage-agent
version: "2.1.0"
description: >
Triages incoming support tickets by analyzing content, classifying
priority, and routing to the appropriate team. Handles 500+ tickets/day
with 99.5% contract satisfaction.
authors:
- Piyush Vyas
name: repo-build-agent
version: "0.1.0"
description: Fail-closed coding/build agent for this repository.

contract:
postconditions:
- name: produces_classification
- name: produces_output
check: "output is not None"
enforcement: sync_block
severity: critical
description: Must always produce a triage result.
description: The run must produce a result object.

- name: valid_priority
check: 'output.priority in ["critical", "high", "medium", "low"]'
- name: repo_checks_green
check: "checks.pytest.exit_code == 0 and checks.ruff.exit_code == 0"
enforcement: sync_block
severity: critical
description: Priority must be one of the defined levels.

- name: has_routing
check: 'output.routed_to is not None'
enforcement: sync_warn
severity: major
description: Should route to a team (warn if not).
slo:
target_rate: 0.99
window: "24h"

- name: response_quality
check: "eval:quality_judge"
enforcement: async_monitor
severity: minor
description: LLM-as-judge quality assessment (async, not blocking).
slo:
target_rate: 0.95
window: "7d"

inputs:
schema:
type: object
required:
- ticket_id
- subject
- body
properties:
ticket_id:
type: string
subject:
type: string
body:
type: string
customer_tier:
type: string
enum: ["enterprise", "business", "starter", "free"]
attachments:
type: array
items:
type: object
properties:
filename:
type: string
url:
type: string

preconditions:
- name: ticket_not_empty
check: "len(input.body) > 0"
description: Ticket body must not be empty.

outputs:
schema:
type: object
required:
- priority
- category
properties:
priority:
type: string
enum: ["critical", "high", "medium", "low"]
category:
type: string
routed_to:
type: string
summary:
type: string
suggested_response:
type: string
confidence:
type: number
minimum: 0
maximum: 1
description: Required repo checks must pass before the run is green.

effects:
authorized:
tools:
- ticket_database.read
- ticket_database.update_priority
- ticket_database.assign
- customer_lookup
- knowledge_base.search
- notification.send_team
network:
- "https://api.ticketing.internal/*"
- "https://api.customers.internal/*"
- "https://kb.internal/*"
state_writes:
- "tickets.*"

declared:
tools:
- ticket_database.read
- ticket_database.update_priority
- ticket_database.assign
- customer_lookup
- knowledge_base.search
network:
- "https://api.ticketing.internal/v2/tickets"
- "https://api.customers.internal/v1/lookup"
- "https://kb.internal/search"
state_writes:
- "tickets.priority"
- "tickets.assignment"
filesystem:
read:
- "src/**"
- "tests/**"
- "README.md"
- "pyproject.toml"
write:
- "src/**"
- "tests/**"
- "README.md"
shell:
commands:
- "python -m pytest *"
- "python -m ruff check *"
- "python -m mypy *"
tools: []
network: []
state_writes: []

resources:
budgets:
max_cost_usd: 0.10
max_tokens: 8000
max_tool_calls: 15
max_duration_seconds: 20.0

failure_model:
errors:
- name: ticket_not_found
retryable: false
description: The referenced ticket does not exist.

- name: database_timeout
retryable: true
max_retries: 3
description: Ticket database took too long to respond.

- name: rate_limit
retryable: true
max_retries: 2
fallback: queue-agent
description: API rate limit exceeded, queue for later processing.

- name: classification_uncertain
retryable: false
fallback: human-review-queue
description: Agent confidence too low for automated triage.

default_timeout_seconds: 20.0

circuit_breaker:
failure_threshold: 10
reset_timeout_seconds: 120.0

delegation:
max_depth: 2
attenuate_effects: true
require_contract: true
allowed_agents:
- queue-agent
- human-review-queue
- notification-agent
max_cost_usd: 1.00
max_tokens: 50000
max_tool_calls: 20
max_shell_commands: 10
max_duration_seconds: 1800

observability:
traces:
enabled: true
sample_rate: 1.0

metrics:
- name: triage_latency_ms
type: histogram
description: End-to-end triage latency.
- name: triage_total
type: counter
description: Total tickets triaged.
- name: priority_distribution
type: gauge
description: Current distribution of ticket priorities.

violation_events:
emit: true
destination: otel

versioning:
build_id: "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
breaking_changes: []
substitution:
compatible_with:
- "2.0.0"

slo:
contract_satisfaction_rate:
target: 0.995
window: "24h"

latency:
p50_ms: 800
p99_ms: 5000

cost:
avg_usd: 0.04
p99_usd: 0.10

error_budget_policy: freeze_deployments
run_artifact_path: ".agent-contracts/runs/{run_id}/verdict.json"
Loading
Loading