Linear
Linear's GraphQL API is well-behaved. One issueCreate makes an issue; a missing required field is a clear error naming it ('IssueCreateInput.teamId ... was not provided'); and a chain works - create an issue, comment by issueId, move it to Done by stateId, read back. Bad inputs are caught: priority:99 is INVALID_INPUT, a nonexistent assigneeId returns 'Entity not found in validateAccess: assigneeId'. Idempotency is opt-in: pass your own UUID as the issue id and a retry with the same id fails 'conflict on insert', but the default no-id path makes two identical calls produce two issues.
Cross-validated onClaude Opus 4.8
The five tasks
Getting started from the docs aloneNailed it
Fixing its own mistake after an errorNailed it
Following a multi-step flowNailed it
Handling an unclear edge caseNailed it
Not double-charging on a retryHalf-nailed it
Here’s the receipt — what actually happened, not our summary of it.
Two paths. WITH a client-supplied id: issueCreate(input:{id:<uuid>, teamId, title}) succeeds once (AGE-6); a second call with the SAME id -> 'conflict on insert of Issue' INPUT_ERROR userError:true (no duplicate). WITHOUT an id (the default): two identical issueCreate calls return two different issues (AGE-7 and AGE-8) = duplicate. So retries are safe only if the agent proactively generates and reuses its own id; the naive path duplicates.See everything the AI did (5 steps)
t1 Claude Opus 4.8 issueCreate(teamId, title) → 200 success, AGE-5 t2 Claude Opus 4.8 issueCreate (teamId omitted) → 400 names IssueCreateInput.teamId t3 Claude Opus 4.8 issueCreate -> commentCreate(issueId) -> issueUpdate(id, stateId) -> issue(id) → chain ok: comment created, state=Done, read back t4 Claude Opus 4.8 issueCreate priority:99 ; issueCreate bad assigneeId → INVALID_INPUT validationErrors ; 'Entity not found: assigneeId' t5 Claude Opus 4.8 issueCreate same client id x2 ; issueCreate no id x2 → conflict on insert (deduped) ; AGE-7 + AGE-8 (duplicate)
Tested 2026-07-04 with Claude Opus 4.8 agents · request a re-test