> For the complete documentation index, see [llms.txt](https://kerno.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kerno.gitbook.io/docs/references/kerno-mcp.md).

# Kerno MCP

Kerno's MCP tools are the API your coding agent uses to drive Kerno.

### Async job pattern

Entry point tests, flow tests, validation runs and batches are async, because the underlying work can take minutes. Async tools return a `job_id` and a `kind` identifying the operation. Call `kerno_job` to wait for the result. `kerno_environment_setup` is synchronous, and returns a `job_id` only when it starts a background `healthcheck_author` job.

MCP hosts typically enforce a \~60-second timeout on a single tool call. `kerno_job` with `wait=true` blocks for at most 15 seconds, then returns the current snapshot with `wait_timed_out`, so call it again. Use `wait=false` for one immediate snapshot, block on the resource with `kerno_get_state` or `kerno_await_state`, or poll `GET /mcp/jobs` over HTTP.

When a job finishes, `kerno_job` reports `healthy`, `failed` or `cancelled`, or `completed` for a batch, and the result is also available via `GET /mcp/jobs`. A job parked at a feedback gate reports `needs_user_feedback` and resumes once the gate is answered. The last 50 finished jobs stay readable.

To cancel in-flight work, call `kerno_cancel` with a `job_id`, or with a `resource_id` or `batch_id` to stop one batch member or a whole batch. Cancellation is fire-and-forget, and the next `kerno_job` call returns `status: cancelled`.

{% hint style="info" %}
**Feedback gates show on the job.** When an entry point test pauses for plan approval or an answer, `kerno_job` reports `needs_user_feedback` with the prompt in `summary`, and `GET /mcp/jobs` reports the same status. Fetch the plan or question with `kerno_feedback_pending`, then answer with `kerno_feedback_answer`.
{% endhint %}

### Next action

Every response your agent waits on carries one `next_action` string, the step to take next. It is usually a tool call with its arguments, and sometimes a result to present or a question for the user. An empty `kerno_list_endpoints` result says why it is empty. `next_action` replaces the earlier `next_step` and `recommended_next_action` fields.

### Tools

#### Workspace management

| Tool                    | Description                                                                                                                                                                                                                                                                                            |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `kerno_sync_workspace`  | Sync Kerno's view of the workspace with the current state of code on disk. Cancels running Kerno operations, takes a fresh snapshot, and re-runs workspace analysis. Call this after making code changes.                                                                                              |
| `kerno_list_workspaces` | List the workspaces Kerno is managing, including snapshot state (branch, commit, uncommitted changes) and active jobs.                                                                                                                                                                                 |
| `kerno_clear_cache`     | Clear Kerno's cached state. Without `application_id`, it resets the whole workspace, including running jobs and learned memory, then re-runs analysis. Calibration declines are kept unless you pass `drop_declines: true`. With `application_id`, it resets only that application's test environment. |
| `kerno_list_mcp_tools`  | Introspect the MCP tools, resources and prompts your MCP server exposes. Pass `mcp_url` to query the running server and record what it advertises. Omit it to list what Kerno has recorded, detected from source the first time.                                                                       |

#### Discovery

| Tool                     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kerno_healthcheck`      | Check agent health, Docker, git, authentication, and codegraph. `workspace_path` is optional; defaults to the agent workspace.                                                                                                                                                                                                                                                                                                                                                                                                     |
| `kerno_get_applications` | Analyze the workspace and list applications Kerno detected, split into supported and unsupported, with each app's current config summary and its `next_action`.                                                                                                                                                                                                                                                                                                                                                                    |
| `kerno_list_endpoints`   | Browse what analysis found, grouped by source file, with which entry points already have tests. Covers HTTP routes, background consumers and the MCP primitives found in source, plus routes Kerno located on demand for a test. Tools a running MCP server advertises are listed by `kerno_list_mcp_tools`. Requires a `scope`, and can be filtered by app, coverage, method, protocol or file. With scope `changed`, it also returns the `impactedFlows` to re-run. The first call can take a few minutes on a large repository. |
| `kerno_graph`            | Return the workspace as a graph of applications, their entry points, the tests and flows that cover them, and their downstream services. It reads the entry point analysis already done, so it returns in seconds, and `analysis_pending` names the apps still to analyse. Its first call on a workspace also registers and analyses the workspace, so hosts may ask before running it. Hosts that support MCP Apps show it as an interactive graph that highlights what a running test touches.                                   |

#### Environment

| Tool                       | Description                                                                                                                                                                                                                                                                                                                                                                                          |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kerno_save_config`        | Save how to reach your applications, one `applications` entry per app with its `target_environment` (`local` or `remote`) and `sut_url`, the URL as reached from your machine. An entry can also declare datastore access, downstream HTTP services, and which infrastructure Kerno may touch. Kerno probes the URL before saving, and saving an app starts its security analysis in the background. |
| `kerno_environment_setup`  | Probe the application and prepare it for entry point testing. Synchronous. Accepts an optional `sut_url` to save first, and returns `ready_for_endpoint_test` with the next step.                                                                                                                                                                                                                    |
| `kerno_environment_status` | Report readiness. Check `ready_for_endpoint_test` before running a test. Also reports the latest per-component health check, and `refresh_health: true` runs it now.                                                                                                                                                                                                                                 |

{% hint style="warning" %}
**Keep secret values in `.kerno/.env`.** `kerno_save_config` writes its blocks to `.kerno/config.yaml`, which is meant to be committed. In the block, declare only the variable name, with a placeholder value. Put the real value in `.kerno/.env`, which Kerno gitignores and merges in at higher precedence.
{% endhint %}

Kerno does not build or run your application. You start it yourself, then tell Kerno where it is. See [Environment Setup](/docs/core-concepts/environment-setup.md).

#### Entry point testing

| Tool                         | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kerno_endpoint_test`        | Async. Generate or update tests for a single entry point. To re-run existing tests, use `kerno_validate`. Returns `job_id`, kind `endpoint_test`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `kerno_endpoint_test_many`   | Dispatches `kerno_endpoint_test` with `type` `generate` or `update` across many entry points in one call. Returns at once with a `batch_id` and one row per member, and runs as a job you can follow or cancel.                                                                                                                                                                                                                                                                                                                                                                                                   |
| `kerno_flow_test`            | Async. Plans, implements and runs one user-flow test, an ordered walk across several entry points. Takes `app`, a kebab-case `flow_id`, the user's own `flow_description`, and the `endpoints` in the order the user hits them. Optional `outcome` states what must hold once the flow succeeds, and `test_generation_context` adds guidance as on `kerno_endpoint_test`. Effort, box strategy and tags are fixed at `high`, `white_box` and `validation`. The test is stored under `.kerno/scenarios/flows/<flow_id>/`, and running the same `flow_id` again revises it. Returns `job_id`, kind `endpoint_test`. |
| `kerno_save_flows`           | Records the user flows you confirmed, without running them. Takes `app` and a `flows` list in the same shape as `kerno_flow_test`. Each flow comes back `saved` or `rejected` with the reason. A flow over HTTP routes that analysis has not found is still saved.                                                                                                                                                                                                                                                                                                                                                |
| `kerno_validate`             | Async. Re-runs the tests already on disk against your live stack and compares them with their baselines. Pass `endpoints` and `flows` to choose what to run. With neither, it validates every known entry point, and any entry point without tests reports "No scenarios found". A flow runs only when named in `flows`. Returns `job_id`, kind `validate`, with a Portal link for each entry point or flow. Each result carries a `fault_class` naming which side is at fault, such as `bad_environment`, and a `fault_reason` when the run stopped before any test was judged.                                  |
| `kerno_ignore_potential_bug` | Record that a reported potential bug is known or intended. Later run reports for that entry point, `kerno_validate` included, leave it out. The test file keeps its flag until a `type: update` run rewrites it, and a full `kerno_clear_cache` discards the decision.                                                                                                                                                                                                                                                                                                                                            |

`kerno_endpoint_test` arguments:

| Argument                  | Required | Values                                                                                                                                                                                                             |
| ------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `workspace_path`          | yes      | absolute path                                                                                                                                                                                                      |
| `app`                     | yes      | application id from `kerno_get_applications`                                                                                                                                                                       |
| `endpoint_method`         | yes      | e.g. `GET`. For an MCP primitive, pass `TOOL`, `RESOURCE` or `PROMPT`. For a background consumer, pass `TASK` or `MESSAGE`                                                                                         |
| `endpoint_path`           | yes      | e.g. `/api/users`. A route analysis didn't list is located from its handler before the run, and refused only if no handler is found. For an MCP primitive, pass its name. For a consumer, pass its registered name |
| `type`                    | yes      | `generate` \| `update`                                                                                                                                                                                             |
| `effort`                  | no       | `low` \| `medium` \| `high`, default `high`. An entry point marked critical in the Portal always runs `high`                                                                                                       |
| `box_testing_strategy`    | no       | `black_box` \| `white_box`, default `white_box`                                                                                                                                                                    |
| `tags`                    | no       | `validation` (default) and/or `security`                                                                                                                                                                           |
| `test_generation_context` | no       | free-text guidance for this entry point                                                                                                                                                                            |
| `scenario_ids`            | no       | target specific scenarios only                                                                                                                                                                                     |
| `interactive`             | no       | boolean, default `false`                                                                                                                                                                                           |

See [Testing modes](/docs/references/testing-modes.md) for what each of these changes.

{% hint style="info" %}
**Testing MCP tools.** `kerno_endpoint_test` also tests the tools your MCP server exposes. Address a tool with `endpoint_method: TOOL` and `endpoint_path` set to the tool's name. Discover what is testable with `kerno_list_mcp_tools`. Kerno reaches the server over Streamable HTTP at the MCP path in your `sut_url`. A test can also call a tool without your auth headers. The run report and `kerno_validate` mark each such call `unauthenticated`, with a `rejection` holding the status code and message when the server refused it. See [Baseline tests](/docs/core-concepts/scenarios-and-baselines.md#testing-mcp-servers).
{% endhint %}

The launch response carries the `job_id`, a `monitoring_command` to block on until the plan needs your approval or the run finishes, and a `portal_run_url` for the run's Portal page. The finished `ready` state carries the same `portal_run_url`. Its `resolved_intent` shows which values Kerno used and which it defaulted, and `effort_forced_by` appears when a critical entry point raised the effort.

#### Testing many entry points in one call

`kerno_endpoint_test_many` applies the same dials to a list of entry points. It returns straight away with a `batch_id`, a `job_id` and one row per member, each with the `resource_id` to quote back verbatim. To stop the batch, pass either id to `kerno_cancel`.

| Argument         | Required | Values                                                                                         |
| ---------------- | -------- | ---------------------------------------------------------------------------------------------- |
| `workspace_path` | yes      | absolute path                                                                                  |
| `app`            | yes      | application id                                                                                 |
| `endpoints`      | yes      | the entry points to cover                                                                      |
| `type`           | yes      | `generate` \| `update`                                                                         |
| `plan_approval`  | no       | `auto` (default) \| `gate`                                                                     |
| `max_in_flight`  | no       | caps how many members run at once, default 16. A member parked at its plan gate keeps its slot |

`effort`, `box_testing_strategy`, `tags` and `test_generation_context` apply to every member.

Under `plan_approval: auto` the plan gate never fires, so there is nothing to poll for. Under `gate`, members pause at the real plan gate and you answer each one with `answer_feedback_request`. Find the waiting members by blocking on `kerno_await_state` with the `batch_id`.

Each entry point is validated as it is dispatched. One that cannot be tested comes back with `admission` set to `rejected` along with the reason, and the rest of the batch carries on. Members over the `max_in_flight` cap come back `queued` and are promoted automatically.

This tool takes an explicit entry point list rather than a [scope](/docs/references/scopes.md).

#### Feedback gate

When Kerno needs input, such as a plan approval, a planner question, or missing credentials, it opens a feedback request on the relevant resource.

| Tool                      | Description                                                                                                                                                                                         |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kerno_feedback_pending`  | Read-only list of the open feedback requests for one app, such as a plan awaiting approval, each with its `request_id`, `prompt` and `resource_id`. Returns `status: none` when nothing is waiting. |
| `kerno_feedback_answer`   | Answer by `workspace_path` + `app` + `request_id`. Payload is free-text `{"answer":"..."}` or approval `{"approved":true}` / `{"approved":false,"reason":"..."}`. Returns `accepted` once queued.   |
| `answer_feedback_request` | Answer by `resource_id` (the `.../feedback` subresource) + `request_id`. Same payload shape. Use this when you already have the `resource_id` from `kerno_get_state`.                               |

`kerno_feedback_answer` and `answer_feedback_request` reach the same action, so use whichever is more convenient given the context you already have.

#### Lesson review

Kerno writes down what it learns from your test runs and from analysing your code, and reuses it when planning later runs. These two tools let your agent see those records and judge them.

| Tool                    | Description                                                                                                                                                                                                                                         |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kerno_lessons_pending` | Lists the records nobody has reviewed yet, each lesson with the entry points it covers and the runs that back it, and each analysis finding with the document it came from. `pending_total` is the full backlog, which can be larger than one page. |
| `kerno_review_lessons`  | Records a verdict on each record. `agree` keeps it and marks it checked. `amend` replaces its wording with yours. `disagree` retires a lesson for good and sets an analysis finding aside. Send every verdict in one call.                          |

Call these once a batch of entry point tests has finished, before starting the next one.

Kerno carries on using a lesson nobody has reviewed, and labels it as unchecked while it does. Reviewing never holds up a run. See [Memory and learning](/docs/core-concepts/memory-and-learning.md).

#### State plane

These tools let your agent read and watch the state of Kerno resources without polling a job.

| Tool                | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kerno_get_state`   | Read a resource's current state by `resource_id`. Returns `{resource_id, state}` where `state.status` is the variant tag, or `state=null` if the resource has never started. Pass `until_status` to long-poll until the status enters that set. `wait_timeout_ms` then defaults to 15000 ms, which is also the maximum, and a longer value is clamped. Without `until_status` the call returns immediately. `timed_out=true` is a normal outcome, so re-issue with the same `until_status`. Waiting states surface `open_feedback {resource_id, request_id, prompt}`.                                                                                         |
| `kerno_list_state`  | List every started resource under an optional `prefix`. Returns `{resources: [{resource_id, state}], timed_out}`. Pass `until_status` to wait until any of them enters that set, up to 15000 ms.                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `kerno_await_state` | Wait for a batch of resources to reach a terminal status in one call. Name the set either by the `resource_id`s you dispatched or by the `batch_id` `kerno_endpoint_test_many` returned. `satisfy="all"` (default) returns once every id's status is in `until_status`. `satisfy="any_new"` returns as soon as an id that was already outside `until_status` enters it, so you can consume completions one at a time. Returns `{resources: [{resource_id, state}], timed_out}`. Use this in place of a polling loop. `any_new` is edge-triggered against the board as the call begins, so use `kerno_poll_events` when you need a cursor you can resume from. |
| `kerno_poll_events` | Replay domain events since a cursor. Returns `{stream_epoch, next_cursor, gap, events: [{seq, resource_id, event}]}` oldest-first. Start at `cursor=0`, then pass `next_cursor` back verbatim. If `stream_epoch` changes, the agent restarted, so reset to 0. If `gap=true`, events fell off the buffer, so re-read state. Accepts `prefix`, `max_events` (default 256) and `wait_timeout_ms` (maximum 15000 ms). There is no default wait here, so omit `wait_timeout_ms` for an immediate return.                                                                                                                                                           |

`kerno_get_state`, `kerno_list_state` and `kerno_await_state` take `view: compact`, which returns one short row per resource with its `resource_id`, `status`, `job_id`, `request_id`, `feedback_resource_id`, `endpoint`, `outcome`, `fault_class`, `portal_run_url`, `passed`, `total` and `elided_bytes`. Re-read a resource with `view: full` for its plan and per-scenario detail. `kerno_await_state` also takes `view: counts`, which returns how many members sit in each status plus the rows that reached `until_status`.

**Resource id formats.** Entry point tests use a different shape from analyses, so match carefully:

```
workspace/<ws>/app/<app>/endpoint/<METHOD>/<path>/endpointtest
workspace/<ws>/app/<app>/endpoint/FLOW/<flow_id>/endpointtest
workspace/<ws>/module/<app>/securityanalysis
workspace/<ws>/module/<app>/externalservicesanalysis
workspace/<ws>/module/<app>/buildanalysis
<any of the above>/feedback        ← feedback subresource
```

Note `app/` in the entry point test form versus `module/` in the others. Each entry point test component is one percent-escaped segment, so the path `/api/users` appears as `%2Fapi%2Fusers`. Quote ids from tool responses verbatim.

#### Job lifecycle

| Tool / Endpoint | Description                                                                                                                                                                                                                                                               |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kerno_job`     | Wait for or snapshot an async job. `wait=true` (default) blocks for at most 15 seconds, then returns the current snapshot with `wait_timed_out` if the job is still going. `wait=false` returns one immediate snapshot. Pass the `job_id` returned by the launching tool. |
| `kerno_cancel`  | Cancel in-flight async work by `job_id`, by a batch member's `resource_id`, or by `batch_id`. Fire-and-forget. The next `kerno_job` call returns `status: cancelled`.                                                                                                     |
| `GET /mcp/jobs` | HTTP endpoint. List active and recently-completed jobs as `McpJobSnapshot` objects. Supports `?since=<ISO-8601>` and `?status=<value>` (repeatable) filters.                                                                                                              |

### Job snapshots

`GET /mcp/jobs` returns an array of `McpJobSnapshot`. Use it for lightweight HTTP polling, or to retrieve a completed job's result after the MCP session has ended.

```json
{
  "jobId": "abc123",
  "kind": "endpoint_test",
  "app": "backend-api",
  "status": "healthy",
  "startedAt": "2026-07-25T10:00:00Z",
  "lastActivityAt": "2026-07-25T10:02:15Z",
  "completedAt": "2026-07-25T10:02:15Z",
  "activityLogTail": ["...last 20 lines of the activity log..."],
  "scope": {
    "endpoints": [
      { "app": "backend-api", "method": "GET", "path": "/api/items" }
    ]
  },
  "terminalPayload": { }
}
```

| Field             | Type               | Notes                                                                                                                                                          |
| ----------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `jobId`           | string             | Same ID returned by the launching MCP tool.                                                                                                                    |
| `kind`            | string             | `validate`, `endpoint_test`, `endpoint_test_many`, `healthcheck_author`, `security_analysis`, `build_analysis`, `external_services_analysis` or `calibration`. |
| `app`             | string             | Application the job targets.                                                                                                                                   |
| `status`          | string             | `running`, `needs_user_feedback` (parked at a gate, resumes once answered), `healthy`, `failed`, or `cancelled`.                                               |
| `startedAt`       | ISO-8601 timestamp |                                                                                                                                                                |
| `lastActivityAt`  | ISO-8601 timestamp | Updated on each activity log write and on completion.                                                                                                          |
| `completedAt`     | ISO-8601 timestamp | Null while running.                                                                                                                                            |
| `activityLogTail` | string\[]          | Last 20 lines of the activity log. `kerno_job` returns the full log in its `activity_log` field.                                                               |
| `scope`           | object (nullable)  | Resolves once the job starts processing. Lists the entry points targeted by this job.                                                                          |
| `terminalPayload` | object (nullable)  | Present on completion for `endpoint_test` and `validate` jobs. Holds the run's result (summary, entry point and scenario results), as `kerno_job` returns it.  |

**Query params:**

* `?since=<ISO-8601>` returns only jobs where `lastActivityAt >= since`.
* `?status=<value>` filters by status. Repeatable, as in `?status=running&status=failed`.

The last 50 finished jobs are kept. Snapshots are read-only, so use `kerno_cancel` to cancel a running job.

### MCP resources

The Kerno agent publishes MCP resources alongside its tools:

```
kerno://workspaces/{workspaceId}/scenarios
kerno://workspaces/{workspaceId}/scenarios/{+path}
kerno://workspaces/{workspaceId}/preconditions
kerno://workspaces/{workspaceId}/preconditions/{+path}
kerno://workspaces/{workspaceId}/flows
kerno://workspaces/{workspaceId}/flows/{flowId}
ui://kerno/graph
```

Scenario, precondition and flow resources are scoped per workspace. The list templates return what a workspace holds, and the content templates return one file or flow. The flows list returns each app's recorded flows, each with its `app`, `id`, `description`, `outcome` and `steps`, plus a `next_action`. It stays empty until `kerno_save_flows` or `kerno_flow_test` records a flow. `ui://kerno/graph` is the MCP App view that `kerno_graph` opens in hosts that support MCP Apps.

### Skills

Kerno ships its guidance for your agent as skills. Kerno installs them into your repository under `.agents/skills/`, and the MCP server also serves them through `skills/list` and `skills/get` for clients that support MCP skills. Your agent loads each one when the task calls for it.

| Skill                              | What it covers                                                                                                               |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `kerno-endpoint-test-intent`       | Choosing `effort`, `box_testing_strategy` and `tags` before the first entry point test, and checking your saved preferences. |
| `kerno-rules-template`             | A copy-paste preference table for your own rules file.                                                                       |
| `kerno-env-visibility`             | What Kerno can see in your running environment, and where saved settings and secrets go.                                     |
| `kerno-calibrate`                  | The once-per-repo calibration that runs after your application is connected.                                                 |
| `kerno-choosing-a-user-flow`       | Mapping your repository's user flows and choosing one that can run.                                                          |
| `kerno-scenario-philosophy`        | Why Kerno tests behaviour that a framework or library already enforces.                                                      |
| `kerno-presenting-results`         | Presenting a test plan awaiting approval, and run results.                                                                   |
| `kerno-presenting-diffs`           | Presenting a detected diff, and deciding with you whether to fix it or accept it.                                            |
| `kerno-presenting-coverage`        | Presenting entry point coverage from `kerno_list_endpoints`.                                                                 |
| `kerno-reviewing-lessons`          | Reviewing the lessons Kerno has learned before the next run.                                                                 |
| `kerno-baseline-coverage-at-scale` | Running baselines across a whole repository with `kerno_endpoint_test_many`.                                                 |
| `kerno-usage`                      | Writing a short Kerno usage note into your agent's own instruction files.                                                    |

### Common patterns

A typical first run looks like this.

1. `kerno_healthcheck` to confirm Docker, git, and auth.
2. `kerno_get_applications` to discover applications and pick one.
3. Start your application yourself, using its own dev flow.
4. `kerno_save_config` with an `applications` entry carrying `target_environment`, `sut_url`, and the variable names of any datastore credentials. Their secret values go in `.kerno/.env`.
5. `kerno_environment_setup`, then `kerno_environment_status` until `ready_for_endpoint_test` is true.
6. Run the `kerno-calibrate` skill, once per repository. Skip it when `.kerno/config.yaml` already holds a `calibration` record.
7. Read `kerno://workspaces/{workspaceId}/flows` and follow its `next_action`. Flows come first. With none recorded, map them with the user through the `kerno-choosing-a-user-flow` skill, save the ones they confirm with `kerno_save_flows`, and offer to test one. With flows recorded, show them as a numbered list and let the user pick.
8. `kerno_flow_test` for the chosen flow. Its dials are fixed, so there is nothing to ask about effort, box strategy or tags.
9. Block on the launch response's `monitoring_command` until it exits at the plan-approval gate. `kerno_job` reports the same gate as `needs_user_feedback`.
10. Read the plan with `kerno_feedback_pending`, then approve it via `kerno_feedback_answer`.

Entry point tests come up when the user asks for one. Run `kerno_endpoint_test` with `type: generate` for that entry point, by method and path. `kerno_list_endpoints` lets you browse what analysis found and which entry points already have tests.

An app served as an MCP server is the exception. Once its environment is ready, `next_action` points to `kerno_list_mcp_tools` with the server's MCP URL, then one `kerno_endpoint_test` per tool with `endpoint_method: TOOL` and the tool's name as `endpoint_path`.

After a code change, call `kerno_sync_workspace`, then `kerno_validate`. Pass the entry points that `kerno_list_endpoints` returns with scope `changed`, and its `impactedFlows` as `flows`, or leave out both to validate every known entry point. If an entry point changed on purpose and its tests should follow, run `kerno_endpoint_test` with `type: update`.

### Notes for agent integrators

* Use absolute workspace paths when tools request `workspace_path`. It is the selector for which workspace the call targets, so pass the one you mean on every call. The agent accepts its startup workspace and any directory nested under it, and holds several at once.
* Do not poll `kerno_job` in a tight loop. Let `wait=true` do the waiting, up to 15 seconds per call, block on `kerno_get_state` or `kerno_await_state`, or use `GET /mcp/jobs`.
* **Feedback gates show on the job.** A gated entry point test reports `needs_user_feedback` on `kerno_job`, and its state resource carries `open_feedback`.
* Do not manually edit scenario files under `.kerno/scenarios/`. To change them, run `kerno_endpoint_test` with `type: update` or `type: generate`.
* A second launch of the same entry point test with the same settings is refused while the first is running, and a batch rejects any member whose entry point is already under test.
* After making code changes, call `kerno_sync_workspace` before `kerno_list_endpoints` or `kerno_endpoint_test`.
* While an entry point test runs, block on its `monitoring_command`. The command needs `curl` and `jq`. Without them, poll `kerno_feedback_pending` and `kerno_get_state` yourself.
* For long-poll calls, `timed_out=true` is a normal outcome, so re-issue immediately with the same parameters.
