Metadata-Version: 2.4
Name: boilerplate-devops-investigation-agent
Version: 0.1.0
Summary: Reusable read-only DevOps Deep Agent boilerplate
Requires-Python: <4,>=3.11
Description-Content-Type: text/markdown
Requires-Dist: deepagents==0.7.22
Requires-Dist: fastapi<1,>=0.115
Requires-Dist: pydantic<3,>=2.10
Requires-Dist: uvicorn<1,>=0.30
Provides-Extra: aws
Requires-Dist: boto3<2,>=1.35; extra == "aws"
Requires-Dist: langchain-aws<2,>=1.8; extra == "aws"

# boilerplate-devops-investigation-agent

Reusable Deep Agent boilerplate. Start each real agent in its own repository
and keep this repository as the common starter. The Python import package
remains `devops_agent`; choose your own distribution name in `pyproject.toml`
when creating a new agent.

It imports no harness code.
The factory uses Deep Agents 0.7.22 with an explicit model, in-memory skills,
and a bounded CloudWatch Logs tool. Tests use fake models and clients.
The shared [phase protocol](protocol/README.md) is **`deep-agent/1.0.0`**.
It includes typed input/output models, JSON schemas, validated handoffs,
and a complete synthetic GENERATE → RANK → SELECT → EXECUTE exchange.
Opt-in RANK and SELECT model handlers use saved, hash-checked evidence.
The opt-in [local runtime](LOCAL_RUNTIME.md) adds GENERATE/EXECUTE Deep Agents,
independent review, shared model-spend guards, SQLite records and a Podman
code worker. Live provider, AWS and harness setup still require explicit wiring.

## Local development

Install [uv](https://docs.astral.sh/uv/getting-started/installation/) and Make,
then run from this repository's root:

```sh
make setup
make start
```

Open `http://127.0.0.1:8080/ping` to check the server. Press Ctrl+C to stop it.
Use `make start PORT=8081` if port 8080 is busy. The server listens only on
your computer by default; set `HOST` explicitly when remote access is needed.

Run `make test` for offline tests, `make check` to check the lock file,
and `make help` (or just `make`) to list commands. `make test-podman` runs the
five optional local worker checks with an already installed Python image.

The Makefile uses the same uv commands below. `.python-version` selects Python 3.13.
`uv sync` creates `.venv` and installs this project in editable mode, along with
the default `dev` group:

```sh
uv sync --locked
uv run --locked pytest -q
uv run --locked python -m devops_agent.runtime
```

`pyproject.toml` declares dependencies; `uv.lock` records the resolved versions
and hashes for the runtime, development group and optional AWS extra.
Commit both files when changing dependencies. `--locked` rejects a stale lock
instead of silently changing it. The declared Python range is wider, but only
Python 3.13 has been checked for this release. See [release checks](RELEASE_PREP.md).

Use `uv add PACKAGE` for a runtime dependency, `uv add --dev PACKAGE` for a
development tool, or `uv remove PACKAGE` to remove one. Use
`uv lock --upgrade-package PACKAGE` for a deliberate update, then run
`uv sync --locked` and the tests.

The runtime command starts the HTTP shell on port 8080. `GET /ping` returns 200.
Valid `POST /invocations` requests return 503 until phase handlers are wired.
Missing or unknown protocol versions return 422.
Health confirms the server is running, not that investigation is ready.

## Code to extend

- `src/devops_agent/agent.py`: `build_agent(model, read_logs)` returns the real
  Deep Agents graph. `investigation_input(question)` loads the bundled skills.
  Both sync and async graph calls are supported. Built-in shell, delegation,
  and file-write tools are hidden and denied. The graph filesystem is in memory.
- `src/devops_agent/tools.py`: `make_read_logs_tool(client, allowed_groups=...,
  start_ms=..., end_ms=...)` makes one `filter_log_events` call per tool call.
  A page is at most 50 events and the window at most 24 hours. These are starter
  defaults, not approved POC run limits. Pagination is reported as incomplete.
- `src/devops_agent/contracts.py`: versioned request/result models for all four
  roles, including candidates, scores, selections, and completed work.
- `src/devops_agent/protocol.py`: `make_response`, `next_request`,
  `validate_handoff`, `validate_response`, hashes, and schema export.
- `src/devops_agent/runtime.py`: `create_app(handlers=..., load_response=...,
  authorize_execute=...)` dispatches typed requests, validates saved upstream
  results, checks EXECUTE authorization, and validates handler responses.
- `src/devops_agent/decisions.py`: `build_decision_handlers` supplies focused
  RANK and SELECT agents with distinct prompts and trace metadata. Models give
  scores or a choice; trusted code preserves and validates the existing packets.
- `src/devops_agent/local.py`: `create_local_app` composes all four phases,
  admission, authorization, model guards and durable replay.
- `src/devops_agent/phases.py` and `phase_tools.py`: GENERATE/EXECUTE graphs,
  actual tool-work records, selected-plan checks and separate review.
- `src/devops_agent/budget.py`: one SQLite-backed US$10 model ledger with
  atomic reservations, usage settlement and a protected review allowance.
- `src/devops_agent/store.py`: owned evidence, immutable work/review records,
  saved responses and invocation claims.
- `src/devops_agent/sandbox.py`: bounded Python experiments in fresh,
  offline Podman containers using a trusted immutable image ID.
- `protocol/v1.0.0/`: JSON Schema 2020-12 files and `example-flow.json`.
  Every message requires `protocol_version`; unknown versions fail closed.

The trusted app must supply AWS account, region, credentials, group allowlist,
and incident window. Do not let the model choose or expand them. Configure the
client with short network timeouts and bounded SDK retries. Use IAM permissions
scoped to the approved log groups; tool checks do not replace AWS permissions.
Use `uv sync --locked --extra aws` when adding the AWS client and chosen Bedrock
model. Include `--extra aws` in subsequent `uv run --locked` commands to keep
that extra installed. Installation alone makes no AWS or paid model calls.
With Make, use `make setup EXTRA=aws` and `make start EXTRA=aws`; the same
`EXTRA=aws` option works for the test targets.

Skills live at `skills/*/SKILL.md`. When running outside the repository root,
set `DEEP_AGENT_SKILLS_DIR` to their absolute path. The Dockerfile includes
them at `/app/skills`. The starter loads all skill descriptions; larger catalogs
need the planned code shortlist before model selection.

## RANK and SELECT wiring

After providing explicit chat models and trusted storage callbacks:

```python
from devops_agent.decisions import build_decision_handlers
from devops_agent.runtime import create_app

handlers = build_decision_handlers(
    rank_model=rank_model,
    select_model=select_model,
    load_evidence=load_evidence,
    max_evidence_bytes=65536,
)
app = create_app(handlers=handlers, load_response=load_response)
```

`load_evidence(context, reference) -> bytes` loads saved UTF-8 evidence.
It must enforce run/app ownership and bound each storage read. The handlers
check SHA-256 and the total byte limit before calling a model. They never
fetch a reference's source URL or perform new AWS reads. The limit rejects
oversized input; it does not silently truncate evidence.
`load_response` is the separate trusted upstream-response loader described
in the [protocol guide](protocol/README.md). Use these handlers through
`create_app` so the upstream origin and handoff are checked first.

Each role makes one `BaseChatModel.invoke` call with its own system prompt,
the admitted task, unchanged phase input, and verified saved evidence.
Use models configured without provider-side tools. These handlers attach
phase, invocation, run, app, and shared budget IDs to LangChain trace metadata;
configure your own trace storage and data controls. No tools are supplied or
dispatched. Tool-call replies, malformed JSON, bad scores, changed packets,
and ineligible choices fail. There is no automatic retry or fallback decision.
SELECT may choose a lower score with a reason, or return `null` to stop.

The internal decision schemas are not new wire messages. Public requests and
responses still use unchanged `deep-agent/1.0.0`. GENERATE and EXECUTE remain
unconfigured in this example. The offline tests use fake models through the
real LangChain interface:

```sh
uv run --locked pytest tests/test_decisions.py -q
```

This wiring does not implement shared spend, provider retry accounting,
deadlines, or durable deduplication. Configure those controls before paid use.
The handlers reject replies over 65,536 UTF-8 bytes after receipt; this is not
a model token limit.

## Before a real investigation

Wire the explicit cheap model, read-only AWS role, trusted source scope,
completed result checks, and independent evidence review into the four
phase handlers. Supply a trusted previous-response loader and EXECUTE
authorizer to `create_app`; the protocol guide describes each callback.

Use the composed local route and its shared `BudgetedModel` guards, trusted
provider token counter, reviewed prices, output/timeout binder and no-hidden-retry
configuration **before enabling paid runs**. The local ledger and replay store
are implemented; their SQLite files must be kept on private durable storage.
Review the [local runtime guide](LOCAL_RUNTIME.md) for the exact callback
contracts, failure behavior and tests. Review chat and learned lessons come later.

The default server cannot start a paid run. Wiring its callbacks is an
explicit development step, not proof that all requirements above are met.
The fake-model tests do not prove live IAM, AgentCore, or harness readiness.

## Container and harness handoff

For a local ARM64 build and health check:

```sh
podman build --platform linux/arm64 -t localhost/devops-agent-starter .
podman run --rm --publish 127.0.0.1:8080:8080 localhost/devops-agent-starter
curl --fail http://127.0.0.1:8080/ping
```

Run `curl` in another terminal. The development image uses a non-root user
and serves `GET /ping` and `POST /invocations` on port 8080. It uses uv 0.11.21
and `uv sync --locked --no-dev --no-editable` to install the locked runtime
without test tools or the optional AWS extra. Before release, pin the base
image digests and record the agent commit, image digest, and AgentCore release.
Add `--extra aws` to the image's sync command when its live provider is wired.

The harness design uses Deep Agents for GENERATE and EXECUTE. GENERATE
explores and tests methods, using permitted log reads and isolated code,
and returns candidate plans with evidence. A focused RANK agent gives scores
under a configured rubric. A focused SELECT agent picks an eligible candidate.
After authorization, EXECUTE does the picked work and checks its result.
It may use further scoped read-only AWS reads and isolated code required by
the plan, while reusing valid work already completed in GENERATE.

Give each role separate inputs, instructions, outputs, and traces; all may
share one package and AgentCore runtime. Trusted code validates score ranges,
candidate IDs, eligibility, and selected-plan scope. RANK and SELECT use saved
evidence only. Record the work EXECUTE actually performs and apply independent
review before passing the checked result to MEASURE. All four agents,
candidates, retries, and review share one US$10 model-spend cap.

The typed protocol, four phase handlers, independent review, local durable
state/budget controls and isolated Podman code runner are implemented.
The built-in shell and file-write tools remain blocked.
Harness adapters, distributed state, an AgentCore sandbox backend, scoped
live AWS setup and paid-provider validation still need implementation/setup.
Use distinct phase-call IDs for duplicate handling under one investigation ID.
Bind EXECUTE to the selected plan's ID/hash and authorized read-only/tool scope.
Preserve completed step outputs to prevent duplicate work on retries.
The existing harness route has not changed.

Develop this as its own repository. When a remote URL and tested full commit
pin exist, use the harness's `skills/embark-devops-agent/SKILL.md` to link it at
`devops/agents/<agent-name>/`. Do not copy the project into that destination.
