Grammarly Document Evaluator
Overview
Run Grammarly's three documented document APIs without inventing a direct-text
endpoint. The helper is dry-run by default. Before upload, it can create a metadata-only
request that reveals only the sanitized presigned origin for approval. Inspection
requires an INSPECTION_READY manifest before OAuth. Live execution requires an exact digest and a READY closed-schema safety manifest bound to the
operation, bytes, and both destinations. It reads OAuth credentials only from the
process environment, bounds polling locally, and emits no token, full upload URL, raw
request identifier, or document text.
Prerequisites
- Grammarly Enterprise or an institution-wide Grammarly for Education license with API access.
- Python 3.10 or newer.
- One supported regular, non-symlink file:
.doc, .docx, .odt, .txt, or .rtf.
- For live execution only,
GRAMMARLY_CLIENT_ID and GRAMMARLY_CLIENT_SECRET in the environment.
- The exact read/write scopes for the selected operation; see API contract.
Instructions
Classify the operation as writing-score, ai-detection, or plagiarism.
Run the helper without --execute from this skill directory:
python3 scripts/run_document_evaluation.py \
--operation writing-score \
--file /approved/input/document.txt
Review the endpoint, scopes, beta marker, local constraints, retention boundary,
and content_sha256. A dry run does not contact Grammarly.
Create a preliminary manifest with presigned_upload_origin: null and
presigned_upload_origin_approved: false. Continue only when the safety guardian
returns INSPECTION_READY, then inspect the actual byte destination. This creates
a provider request but performs no upload and emits no signed URL:
python3 scripts/run_document_evaluation.py \
--operation writing-score \
--file /approved/input/document.txt \
--inspect-upload-origin \
--confirm-content-sha256 sha256:REVIEWED_DIGEST \
--approval-manifest /approved/metadata/grammarly-inspection.json
Put that exact sanitized origin and the dry-run metadata into the closed manifest
for grammarly-data-safety-guardian. Continue only when it returns READY.
If live transfer is authorized, execute with both bindings:
python3 scripts/run_document_evaluation.py \
--operation writing-score \
--file /approved/input/document.txt \
--execute \
--confirm-content-sha256 sha256:REVIEWED_DIGEST \
--approval-manifest /approved/metadata/grammarly-transfer.json
Treat COMPLETED and FAILED as terminal. A local polling-budget exhaustion means
only that this helper stopped; Grammarly documents no processing-time SLA.
Interpret all score fields on the documented 0..1 scale. Never convert them into
unsupported pass/fail policy unless the operator supplies that policy separately.
Output
- Dry run: a JSON transfer plan with content digest, byte size, extension, endpoint,
scopes, beta status, and documented retention boundaries.
- Upload-origin inspection: sanitized public HTTPS origin, hashed request identifier,
hashed full URL, and
document_uploaded: false; the signed path/query remains secret.
- Execute: the same plan plus approved origin, hashed request identifier, terminal
status, and exact API-specific score fields when completed.
- No raw content, OAuth token, client secret, presigned URL, or raw provider body.
Error Handling
| Failure |
Meaning |
Safe response |
| Unsupported, empty, oversized, symlinked, or changing file |
Local safety check failed |
Stop and prepare a new approved regular file. |
Fewer than 30 words or more than 100,000 UTF-8 characters in .txt |
Documented text constraint failed |
Correct the source; do not split and recombine scores. |
| Digest confirmation mismatch |
Reviewed bytes differ from execution bytes |
Stop and repeat dry run and approval. |
| Missing, blocked, or mismatched approval manifest |
Governance decision does not bind this operation, content, phase, or origin |
Stop before OAuth or before upload. |
| Newly issued upload origin differs from the approved inspected origin |
Provider byte destination changed |
Stop before PUT; inspect and approve again. |
| OAuth or API HTTP failure |
Provider boundary rejected the operation |
Report only phase and status code; never dump bodies or credentials. |
| Unknown status or result field |
Response differs from the pinned contract |
Fail closed and verify current official documentation. |
| Polling budget exhausted |
Local cap reached; provider limit is undocumented |
Return deferred/unknown, never fabricate a score. |
Examples
AI detection request: choose ai-detection, disclose that it is Beta, require
ai-detection-api:read,write, and return only average_confidence and
ai_generated_percentage on a 0..1 scale.
“Send this paragraph directly to /v1/check”: refuse that contract. Grammarly's
document APIs require a filename-only creation body, a presigned file upload, and
status polling.
Provider outage: return an explicit unavailable or deferred result. Never substitute
an invented score.
Resources
1---2name: grammarly-document-evaluator3description: Validate, plan, and explicitly execute Grammarly Writing Score, AI Detection, or Plagiarism Detection document jobs using the documented create, presigned upload, and poll lifecycle. Use when an operator needs to score a document, detect AI-generated content, check originality, diagnose a malformed document submission, or verify API result fields. Do not use for browser-editor grammar suggestions, live text rewriting, license deletion, or undocumented webhooks. Trigger with "score this document", "run Grammarly AI detection", "check this document for plagiarism", or "diagnose this Grammarly document job".4license: MIT5---6
7# Grammarly Document Evaluator
8
9## Overview
10
11Run Grammarly's three documented document APIs without inventing a direct-text
12endpoint. The helper is dry-run by default. Before upload, it can create a metadata-only
13request that reveals only the sanitized presigned origin for approval. Inspection
14requires an `INSPECTION_READY` manifest before OAuth. Live execution requires an exact digest and a READY closed-schema safety manifest bound to the
15operation, bytes, and both destinations. It reads OAuth credentials only from the
16process environment, bounds polling locally, and emits no token, full upload URL, raw
17request identifier, or document text.
18
19## Prerequisites
20
21- Grammarly Enterprise or an institution-wide Grammarly for Education license with API access.
22- Python 3.10 or newer.
23- One supported regular, non-symlink file: `.doc`, `.docx`, `.odt`, `.txt`, or `.rtf`.
24- For live execution only, `GRAMMARLY_CLIENT_ID` and `GRAMMARLY_CLIENT_SECRET` in the environment.
25- The exact read/write scopes for the selected operation; see [API contract](references/api-contract.md).
26
27## Instructions
28
291. Classify the operation as `writing-score`, `ai-detection`, or `plagiarism`.
302. Run the helper without `--execute` from this skill directory:
31
32 ```bash
33 python3 scripts/run_document_evaluation.py \
34 --operation writing-score \
35 --file /approved/input/document.txt
36 ```
37
383. Review the endpoint, scopes, beta marker, local constraints, retention boundary,
39 and `content_sha256`. A dry run does not contact Grammarly.
404. Create a preliminary manifest with `presigned_upload_origin: null` and
41 `presigned_upload_origin_approved: false`. Continue only when the safety guardian
42 returns `INSPECTION_READY`, then inspect the actual byte destination. This creates
43 a provider request but performs no upload and emits no signed URL:
44
45 ```bash
46 python3 scripts/run_document_evaluation.py \
47 --operation writing-score \
48 --file /approved/input/document.txt \
49 --inspect-upload-origin \
50 --confirm-content-sha256 sha256:REVIEWED_DIGEST \
51 --approval-manifest /approved/metadata/grammarly-inspection.json
52 ```
53
545. Put that exact sanitized origin and the dry-run metadata into the closed manifest
55 for `grammarly-data-safety-guardian`. Continue only when it returns `READY`.
566. If live transfer is authorized, execute with both bindings:
57
58 ```bash
59 python3 scripts/run_document_evaluation.py \
60 --operation writing-score \
61 --file /approved/input/document.txt \
62 --execute \
63 --confirm-content-sha256 sha256:REVIEWED_DIGEST \
64 --approval-manifest /approved/metadata/grammarly-transfer.json
65 ```
66
677. Treat `COMPLETED` and `FAILED` as terminal. A local polling-budget exhaustion means
68 only that this helper stopped; Grammarly documents no processing-time SLA.
698. Interpret all score fields on the documented `0..1` scale. Never convert them into
70 unsupported pass/fail policy unless the operator supplies that policy separately.
71
72## Output
73
74- Dry run: a JSON transfer plan with content digest, byte size, extension, endpoint,
75 scopes, beta status, and documented retention boundaries.
76- Upload-origin inspection: sanitized public HTTPS origin, hashed request identifier,
77 hashed full URL, and `document_uploaded: false`; the signed path/query remains secret.
78- Execute: the same plan plus approved origin, hashed request identifier, terminal
79 status, and exact API-specific score fields when completed.
80- No raw content, OAuth token, client secret, presigned URL, or raw provider body.
81
82## Error Handling
83
84| Failure | Meaning | Safe response |
85|---|---|---|
86| Unsupported, empty, oversized, symlinked, or changing file | Local safety check failed | Stop and prepare a new approved regular file. |
87| Fewer than 30 words or more than 100,000 UTF-8 characters in `.txt` | Documented text constraint failed | Correct the source; do not split and recombine scores. |
88| Digest confirmation mismatch | Reviewed bytes differ from execution bytes | Stop and repeat dry run and approval. |
89| Missing, blocked, or mismatched approval manifest | Governance decision does not bind this operation, content, phase, or origin | Stop before OAuth or before upload. |
90| Newly issued upload origin differs from the approved inspected origin | Provider byte destination changed | Stop before PUT; inspect and approve again. |
91| OAuth or API HTTP failure | Provider boundary rejected the operation | Report only phase and status code; never dump bodies or credentials. |
92| Unknown status or result field | Response differs from the pinned contract | Fail closed and verify current official documentation. |
93| Polling budget exhausted | Local cap reached; provider limit is undocumented | Return deferred/unknown, never fabricate a score. |
94
95## Examples
96
97**AI detection request:** choose `ai-detection`, disclose that it is Beta, require
98`ai-detection-api:read,write`, and return only `average_confidence` and
99`ai_generated_percentage` on a `0..1` scale.
100
101**“Send this paragraph directly to `/v1/check`”:** refuse that contract. Grammarly's
102document APIs require a filename-only creation body, a presigned file upload, and
103status polling.
104
105**Provider outage:** return an explicit unavailable or deferred result. Never substitute
106an invented score.
107
108## Resources
109
110- [Pinned API contract](references/api-contract.md)
111- [Security and retention boundaries](references/security-boundaries.md)
112- [Deterministic evaluator](scripts/run_document_evaluation.py)
113- [Grammarly developer documentation](https://developer.grammarly.com/)