Skip to main content

Agent Access for Developers

Agent access lets a user give a coding agent a personal access token that calls a limited part of the REST API on their behalf. This page is for developers who add or change what a token can reach. The setup for administrators is in Agent Access, and what it means for instructors is in Working with Coding Agents.

How a request is checked​

A request with a bearer token that starts with art_pat_ is authenticated by PersonalAccessTokenFilter as the token's owner, unless the owner is an administrator. AllowedScopesInterceptor then lets it reach a handler only if the handler carries @AllowedScopes and the token holds every listed scope. The ordinary role annotation of the handler still applies, so a token can do at most what its owner can do in that course, and at most what its scopes allow.

Every endpoint is closed to tokens until you opt it in. That is the point: a new endpoint must not become reachable by an agent by accident.

Opt an endpoint in​

Add @AllowedScopes(AgentScope.X) to the handler, together with an @EnforceAtLeast... annotation and an @Operation with a summary and a description written for an agent, not for a developer: what it does, what it needs, what it refuses. Three rules are enforced by AllowedScopesArchitectureTest:

  • The handler has an @EnforceAtLeast... annotation, because a scope narrows access and never replaces the role check.
  • The handler takes and returns DTOs. The agent specification lists only DTO schemas, so an endpoint that uses a domain object would drop out of it without an error.
  • The committed agent specification lists the handler, with a summary. Regenerate it as described below.

Choose the scope by what the endpoint does. There is deliberately no scope for grades, exams, student data, deleting or publishing; do not add one without a separate threat review.

Keep content a draft​

Exercise and lecture-unit endpoints with the draft-date contract must keep token requests within that contract. AgentDraftRules holds these rules, which apply only to token requests:

  • requireDraftDatesForCreate requires a release date in the future and, if configured, a future start date. Exercise validation separately requires the start date to follow the release date.
  • requireStillDraft lets a token change only content that is not visible yet, and only in a way that keeps it so.
  • rejectExamExercise keeps exam exercises out of reach.

A programming exercise additionally has no student participations, which ProgrammingExerciseDraftGuardService checks. Call the rule before the request is applied to the stored object, and add a test that a token cannot publish through the endpoint. Announcements, competencies and lecture metadata are immediately visible. The MCP announcement and lecture-creation tools therefore require confirmation that the instructor approved the exact text; AgentDraftRules does not hide a newly created lecture.

Regenerate the agent specification​

The agent API specification is generated from the annotations and committed to documentation/static/agent/openapi.yaml, so that it can be published. After you opt an endpoint in or change its documentation, run:

./gradlew generateOpenApiDocs -PopenApiGroup=agent pruneOpenApiSpec -x webapp

The run starts a throwaway server on port 8080 and its SSH server on 7921. If a development server uses them, move the throwaway server with -PopenApiServerPort=<port> and -PopenApiSshPort=<port>. The application specification, which feeds the generated client, is produced by the same command without -PopenApiGroup=agent and covers only the packages listed in gradle/openapi.gradle.

Tools of the MCP endpoint​

/api/core/agent/mcp serves the Model Context Protocol. Its tools, in AgentToolService, are tasks an instructor would name, not wrappers of endpoints, and each one calls the REST API of the same server through AgentApi with the token of the request. Opt the endpoint in first; a tool never grants anything the endpoint does not. A new tool needs a scope that the token must hold to see it, a description that tells the model when to use it and what to confirm first, and typed arguments: a record in AgentToolArguments that the arguments are read as, and a JsonSchemaDTO that describes them to the agent. A body that the tool sends on is the DTO of the endpoint it calls, never a JsonNode; the whole endpoint, protocol messages included, is written with records, as the REST API guideline asks.

Search documentation