{"meta":{"title":"Session limits","intro":"Session limits let an application set an AI Credits budget for a Copilot session. Use sessionLimits when creating or resuming a session to set a soft cap for the current accounting window.","product":"GitHub Copilot","breadcrumbs":[{"href":"/en/copilot","title":"GitHub Copilot"},{"href":"/en/copilot/how-tos","title":"How-tos"},{"href":"/en/copilot/how-tos/copilot-sdk","title":"Copilot SDK"},{"href":"/en/copilot/how-tos/copilot-sdk/features","title":"Features"},{"href":"/en/copilot/how-tos/copilot-sdk/features/session-limits","title":"Session limits"}],"documentType":"article"},"body":"# Session limits\n\nSession limits let an application set an AI Credits budget for a Copilot session. Use sessionLimits when creating or resuming a session to set a soft cap for the current accounting window.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\n## Configure a session limit\n\nSet `maxAiCredits` to the AI Credits soft cap for the session's current accounting window. Usage is checked after model calls return, so one response can exceed the configured value before the runtime blocks the next model call. The SDK forwards this value to the Copilot CLI when it creates or resumes the session.\n\n<div class=\"ghd-codetabs\">\n<div class=\"ghd-codetab\" data-lang=\"typescript\" data-label=\"TypeScript\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">TypeScript</div>\n\n<!-- docs-validate: skip -->\n\n```typescript\nconst session = await client.createSession({\n    onPermissionRequest: approveAll,\n    sessionLimits: {\n        maxAiCredits: 30,\n    },\n});\n\nconst resumed = await client.resumeSession(session.sessionId, {\n    onPermissionRequest: approveAll,\n    sessionLimits: {\n        maxAiCredits: 30,\n    },\n});\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"python\" data-label=\"Python\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Python</div>\n\n<!-- docs-validate: skip -->\n\n```python\nsession = await client.create_session(\n    on_permission_request=PermissionHandler.approve_all,\n    session_limits={\n        \"max_ai_credits\": 30,\n    },\n)\n\nresumed = await client.resume_session(\n    session.session_id,\n    on_permission_request=PermissionHandler.approve_all,\n    session_limits={\n        \"max_ai_credits\": 30,\n    },\n)\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"go\" data-label=\"Go\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Go</div>\n\n<!-- docs-validate: skip -->\n\n```golang\nsession, err := client.CreateSession(ctx, &copilot.SessionConfig{\n\tOnPermissionRequest: copilot.PermissionHandler.ApproveAll,\n\tSessionLimits: &rpc.SessionLimitsConfig{\n\t\tMaxAiCredits: copilot.Float64(30),\n\t},\n})\n\nresumed, err := client.ResumeSession(ctx, session.SessionID, &copilot.ResumeSessionConfig{\n\tOnPermissionRequest: copilot.PermissionHandler.ApproveAll,\n\tSessionLimits: &rpc.SessionLimitsConfig{\n\t\tMaxAiCredits: copilot.Float64(30),\n\t},\n})\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"dotnet\" data-label=\".NET\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">.NET</div>\n\n<!-- docs-validate: skip -->\n\n```csharp\nvar session = await client.CreateSessionAsync(new SessionConfig\n{\n    OnPermissionRequest = PermissionHandler.ApproveAll,\n    SessionLimits = new SessionLimitsConfig\n    {\n        MaxAiCredits = 30,\n    },\n});\n\nvar resumed = await client.ResumeSessionAsync(session.SessionId, new ResumeSessionConfig\n{\n    OnPermissionRequest = PermissionHandler.ApproveAll,\n    SessionLimits = new SessionLimitsConfig\n    {\n        MaxAiCredits = 30,\n    },\n});\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"java\" data-label=\"Java\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Java</div>\n\n<!-- docs-validate: skip -->\n\n```java\nCopilotSession session = client\n        .createSession(new SessionConfig()\n                .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)\n                .setSessionLimits(new SessionLimitsConfig(30.0)))\n        .get();\n\nCopilotSession resumed = client\n        .resumeSession(session.getSessionId(), new ResumeSessionConfig()\n                .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)\n                .setSessionLimits(new SessionLimitsConfig(30.0)))\n        .get();\n```\n\n</div>\n\n<div class=\"ghd-codetab\" data-lang=\"rust\" data-label=\"Rust\"><div class=\"ghd-codetab-fallback-label\" role=\"heading\" aria-level=\"3\">Rust</div>\n\n<!-- docs-validate: skip -->\n\n```rust\nlet limits = SessionLimitsConfig {\n    max_ai_credits: Some(30.0),\n};\n\nlet session = client\n    .create_session(\n        SessionConfig::default()\n            .approve_all_permissions()\n            .with_session_limits(limits.clone()),\n    )\n    .await?;\n\nlet resumed = client\n    .resume_session(\n        ResumeSessionConfig::new(session.id().clone())\n            .approve_all_permissions()\n            .with_session_limits(limits),\n    )\n    .await?;\n```\n\n</div>\n\n</div>\n\n## Observe budget events\n\nApplications can subscribe to session events to update UI when the soft cap changes or the session reaches the exhausted-budget flow.\n\n| Event type | When it is emitted | Important fields |\n|---|---|---|\n| `session.session_limits_changed` | Active session limits changed. A `null` `sessionLimits` value means no limits are active. | `sessionLimits.maxAiCredits?` |\n| `session.usage_checkpoint` | The runtime records durable aggregate usage for resume and accounting. | `totalNanoAiu`, `totalPremiumRequests?` |\n| `session_limits_exhausted.requested` | The session reached the exhausted-budget flow and needs a user decision before continuing. | `requestId`, `maxAiCredits`, `usedAiCredits` |\n| `session_limits_exhausted.completed` | The exhausted-limit prompt was resolved. | `requestId`, `response.action`, `response.additionalAiCredits?`, `response.maxAiCredits?` |\n\nUse the generated event types for the SDK language you are using. For example, TypeScript narrows by `event.type`:\n\n```typescript\nsession.on((event) => {\n    if (event.type === \"session_limits_exhausted.requested\") {\n        showBudgetDialog({\n            requestId: event.data.requestId,\n            maxAiCredits: event.data.maxAiCredits,\n            usedAiCredits: event.data.usedAiCredits,\n        });\n    }\n});\n```"}