# GrantFlow Agent Start

This file is the shortest path for AI agents that need to discover, authenticate, and use GrantFlow without reading the full repository.

## Identity

GrantFlow is an agent-native grant workflow API for donor-aware proposal operations. Use it for preflight checks, governed generation, human review checkpoints, quality/grounding inspection, lifecycle events, and exports.

## Discovery

Read these first:

```text
GET /.well-known/agent-capabilities.json
GET /.well-known/agent-tools.json
GET /.well-known/agent.json
GET /.well-known/agent-policy.json
GET /.well-known/agent-recipes.json
GET /openapi.json
```

The OpenAPI document includes `x-grantflow-agent-recipes` and request examples for agent onboarding, preflight, and generation.
The dedicated recipes endpoint exposes the same workflows as JSON for agents that do not want to parse OpenAPI extensions.

```text
GET /donors
```

Lists supported donors and, per donor, `submission_requirements`: the required DOCX section headings, required XLSX sheets, and ToC sections GrantFlow enforces at export. Fetch this before generation so your draft matches the donor's mandated structure — not following a donor's required structure is a leading cause of automatic disqualification. A `generic` `template_key` means no donor-specific structural template is encoded (empty lists mean "none encoded", not "no donor requirements").

## Go/No-Go Triage

Generation costs effort; many opportunities are not worth bidding. Run a structured go/no-go decision before committing, so you do not spend a generation cycle on a poor-fit opportunity.

```text
POST /decision/bid-no-bid
POST /decision/bid-no-bid/simulate
```

Send 0–100 scores for `strategic_fit`, `win_probability`, `budget_margin`, `delivery_capacity`, `compliance_readiness`, `partner_strength`, `timeline_realism`, `evidence_strength` (flat fields, not nested). Optional `donor_profile` (`usaid` | `eu` | `un` | `giz`) re-weights the criteria; set `mandatory_eligibility_gap: true` or `conflict_of_interest: true` to force a hard `NO_BID`.

The response returns `verdict` (`BID` | `CONDITIONAL_BID` | `NO_BID`), `weighted_score`, `hard_blockers`, `top_risks`, and `must_fix_before_bid`. Treat `NO_BID` and unresolved `hard_blockers` as a stop point. Use `/simulate` to see which score improvements would flip the verdict. The scores are your inputs — GrantFlow does not assess your organization for you.

## Onboarding

Preferred path:

```text
POST /agents/onboarding
```

Use `auth_type=api_key` for sandbox/self-serve API-key onboarding. This returns a bearer API key only when the server enables `GRANTFLOW_AGENT_SELF_SERVE_KEYS_ENABLED=true`.

Use `auth_type=oauth_client_credentials` for OAuth client-credentials onboarding. In sandbox/controlled deployments with `GRANTFLOW_AGENT_SELF_SERVE_KEYS_ENABLED=true`, GrantFlow returns `oauth_client.client_id` and `oauth_client.client_secret` once. Exchange them at:

```text
POST /agents/oauth/token
```

Send the returned access token as `Authorization: Bearer <token>`. In production, OAuth token issuance can still be delegated to the gateway/IAM/API-management layer.

Self-serve API keys are signed credentials with expiry, tenant, and scopes. Agent-critical endpoints enforce `tenant_id` and scopes such as `generate:write`, `status:read`, and `quality:read` when API-key auth is active.

Short-lived runtime sessions:

```text
POST /agents/session
```

Use sessions for bounded runtime work after onboarding. Session credentials inherit tenant and scope constraints and default to a shorter TTL.

Credential introspection:

```text
POST /agents/introspect
X-API-Key: <agent-session-or-operator-key>
```

Bearer tokens are also accepted:

```text
POST /agents/introspect
Authorization: Bearer <agent-access-token>
```

Use introspection before protected runtime calls when an agent needs to confirm active scopes, tenant binding, and expiry.

Credential lifecycle:

```text
POST /agents/credentials/rotate
POST /agents/credentials/revoke
```

Use rotate when a self-serve API key or OAuth client secret may be stale or exposed. Use revoke after rotation, failed handoff, or suspected leakage. Revocation writes to Redis (`GRANTFLOW_REDIS_URL`) when configured, making it durable across restarts. Without Redis, an in-process JTI denylist is used and does not survive process restarts.

Fallback sandbox identity:

```text
POST /agents/register
```

Registration returns `sample_requests.preflight` and `sample_requests.generate`.

## Required Request Discipline

- Send `X-API-Key` or `Authorization: Bearer` when credentials are provided or required.
- Use `request_id` for idempotent write calls.
- Run `/generate/preflight` before `/generate`.
- Treat `pending_hitl` as a stop point unless explicitly authorized to approve checkpoints.
- Inspect `/status/{job_id}/quality` and `/status/{job_id}/events` before export.
- Preserve `tenant_id`, `agent_id`, `job_id`, and `request_id` in your working memory.
- Set an HTTP client timeout of at least 30s on the first call. The hosted demo Space cold-starts when idle, so the first request can take ~30s; warm requests are sub-second.
- Request validation (422) errors follow the same `{ code, message, retryable, next_action }` contract; `code` is `invalid_request` and the failing fields are listed under `errors`.

## Corpus / RAG Ingest

Load reference documents into the RAG corpus before generation to improve grounding.

**Text ingest (agent-native, no file upload):**

```text
POST /ingest/text
X-API-Key: <key>

{
  "text": "<pre-extracted document text>",
  "donor_id": "eu",
  "title": "EU Results Framework 2024",
  "tenant_id": "sandbox_myagent",
  "doc_family": "donor_results_guidance"
}
```

Requires scope `ingest:write`. Chunks and embeds the text immediately.
Returns `chunks_ingested` and `namespace`.

**PDF ingest (operator/script path):**

```text
POST /ingest
Content-Type: multipart/form-data

donor_id=eu_intpa&file=<pdf binary>
```

**Check corpus readiness before generation:**

```text
POST /ingest/readiness   # returns coverage_rate, doc_families, vector_count
GET  /ingest/inventory   # list all ingested documents for a tenant/donor
GET  /ingest/recent      # recent ingest events
```

## Minimal Workflow

```text
POST /decision/bid-no-bid         (optional go/no-go triage before committing effort)
POST /agents/onboarding
POST /agents/oauth/token          (if oauth_client_credentials)
POST /agents/introspect           (verify active scopes)
POST /agents/credentials/rotate   (refresh before long sessions)
GET  /donors                      (donor submission_requirements before drafting)
POST /ingest/text                 (load reference corpus)
POST /ingest/readiness            (confirm corpus coverage)
POST /generate/preflight
POST /generate
GET  /status/{job_id}             (poll until done or pending_hitl)
POST /hitl/approve                (if status == pending_hitl — sets checkpoint decision)
POST /resume/{job_id}             (after approval — dispatches job continuation)
GET  /status/{job_id}             (poll until done)
GET  /status/{job_id}/quality
GET  /status/{job_id}/events
GET  /status/{job_id}/ai-disclosure   (AI-use / provenance disclosure to attach to the submission)
GET  /status/{job_id}/export-payload
POST /agents/credentials/revoke   (after session)
```

`GET /status/{job_id}/ai-disclosure` returns a machine-readable AI-use disclosure: `generation_mode` (`deterministic` | `llm_assisted`), `models`, `grounding` (mode + trust signals), `human_review` (checkpoints + required-before-submission), a `boundary` block, and a paste-ready `human_readable` paragraph. Funders increasingly require disclosure of AI use (for example NIH NOT-OD-25-132, EU disclosure rules). It is a transparency record, not a certification of compliance with any funder's policy and not factuality verification — a human must review before submission.

## MCP

Dependency-free stdio bridge:

```bash
python -m grantflow.mcp.server
```

Production MCP transport with the official Python SDK:

```bash
pip install "grantflow[mcp]"
GRANTFLOW_MCP_TRANSPORT=streamable-http python -m grantflow.mcp.fastmcp_server
```

The official SDK transport is optional so baseline GrantFlow installs stay lightweight.

All 17 MCP tools mirror the HTTP API. Key tools:

| Tool | Wraps | Notes |
|---|---|---|
| `grantflow_onboard_agent` | `POST /agents/onboarding` | Returns credential |
| `grantflow_ingest_text` | `POST /ingest/text` | Text ingest, no file upload |
| `grantflow_run_preflight` | `POST /generate/preflight` | Must run before generate |
| `grantflow_start_generation` | `POST /generate` | Returns `job_id` |
| `grantflow_get_status` | `GET /status/{job_id}` | Poll until terminal |
| `grantflow_hitl_approve` | `POST /hitl/approve` | Unblock `pending_hitl` jobs |
| `grantflow_hitl_list_pending` | `GET /hitl/pending` | Discover waiting checkpoints |
| `grantflow_get_quality` | `GET /status/{job_id}/quality` | Trust summary + critic |
| `grantflow_get_export_payload` | `GET /status/{job_id}/export-payload` | Structured pre-export data |
| `grantflow_run_sandbox_happy_path` | composite | Full smoke workflow in one call |

## Conformance Smoke

Agents can validate the full contract against a running API:

```bash
python -m grantflow.agents.conformance --base-url "$GRANTFLOW_BASE_URL"
```

## Error Handling

All agent-facing endpoints return structured errors:

```json
{
  "detail": {
    "code": "machine_readable_error_code",
    "message": "human readable summary",
    "retryable": false,
    "next_action": "specific recovery action"
  }
}
```

`retryable: true` means the same request may succeed after a brief wait (5xx, rate limit, transient conflict). `retryable: false` means fix the request before retrying.

## Human Boundaries

Do not bypass human-in-the-loop controls. Do not approve HITL checkpoints unless your calling context explicitly grants that authority. Do not export production deliverables until quality, grounding, and review signals have been inspected.
