Skip to content

Limits

Every value Chickpea enforces on attachments, tables, memory, handles, schedules, skill imports, management requests, MCP registration, the coding sandbox, telemetry, and request bodies.

Updated View as Markdown

A limit is a value Chickpea refuses to exceed, checked in code at the moment of the request. Where a setting is chosen in Admin and a quota is billed by Cloudflare or Slack, a limit is compiled into the deployed version and is identical on every deployment of it. This page lists the limits an admin or an operator meets, each with its scope and what happens when a request crosses it.

The source of truth is the Chickpea repository. Every value below was read from the file named at the head of its section. One value is operator-configurable and marked as such: the coding sandbox monthly session cap.

Quick reference

Limit Value Scope
Files read from one message 4 per Slack message
Bytes across one message’s files 12 MiB per Slack message
Rows in a native Slack table 200 per table
Stored Agent memory 64 KiB per Agent
Agent handle 80 characters per Agent
Active schedules 100 per deployment
Active schedules 20 per channel
Minimum interval between runs 5 minutes per schedule
Run-now starts in a rolling 24 hours 10 per deployment
Operations in one management request 25 per request
Skill directories scanned on import 40 per import
Coding sandbox sessions operator setting, uncapped when unset per calendar month

Attachments

Enforced in src/slack/attachment-normalization.ts. Attachments are read for the turn and never stored.

Limit Value At the limit
Files per message 4 No file is read. Every file in the message returns attachment_count_limit_exceeded.
Bytes per file 8 MiB (8,388,608 bytes) The retrieval is bounded to that size, so a larger file fails with a next action of reduce_file_size instead of arriving truncated.
Bytes per message 12 MiB (12,582,912 bytes) Once the running total is spent, each remaining file returns attachment_aggregate_byte_limit_exceeded.
Characters per file after normalization 32,000 The file returns attachment_character_limit_exceeded.
Characters per message after normalization 48,000 The file that crosses the total returns attachment_aggregate_character_limit_exceeded.
Pages in a PDF 100 The file returns pdf_page_limit_exceeded.
Normalization time 13,000 ms per file in the message The file returns attachment_deadline_exceeded.

Files are read in the order they appear on the message, so a small file behind an oversized one can still succeed. Each failure carries a next action: retry, reupload_file, reconnect_slack, convert_file, reduce_file_size, split_file, use_text_pdf, or remove_unsupported_file.

Native Slack tables

Enforced in src/slack/table-presentation.ts, which validates the present_table tool call before Slack sees it.

Limit Value At the limit
Data rows 7 to 200 Six or fewer rows are refused: “Six or fewer data rows should use a compact Markdown table, not a native Slack table.” More than 200 fails schema validation.
Columns 20 Schema validation fails, for the column list and for any row.
Characters across all cells and headers 20,000 “Slack table cells exceed the 20,000-character data-table limit.”
Characters in one text cell 1,000 Schema validation fails.
Characters in a column header 80 Schema validation fails.
Characters in the caption 200 Schema validation fails.
Page size on an explorable table 1 to 100 Schema validation fails. Unset, the page size is the row count or 10, whichever is smaller.
Row header column index 0 to 19 Schema validation fails.
Native tables in one answer 1 “A Slack answer may contain at most one native table presentation.”
Characters in the Markdown fallback 12,000 Rows stop and the fallback ends with _Showing N of M rows._

The model is instructed to summarize instead of calling present_table when a result would exceed 200 rows, 20 columns, or 20,000 cell characters.

Agent memory

Enforced in src/memory/validation.ts and src/memory/store.ts. An Agent has one memory, and a remembered entry is appended to it.

Limit Value At the limit
Description on one write 512 bytes memory_content_too_large, “Description must be at most 512 bytes.”
Body on one write 8 KiB (8,192 bytes) memory_content_too_large, “Body must be at most 8192 bytes.”
Stored memory document 64 KiB (65,536 bytes) memory_entry_too_large, “Agent memory is too large.”

Memory content is also rejected for control characters (memory_invalid_control_character) and for credential-like content (memory_credential_rejected), at any size.

Agent handles

Enforced in src/slack/agent-presence/handles.ts. A handle is a Slack user group with no members.

Limit Value At the limit
Handle length 80 characters The normalized handle is truncated to 80 characters, then any trailing - is removed.
Characters allowed a-z, 0-9, _, - Every other run of characters becomes a single -. Leading and trailing - are stripped.
Empty result none A handle that normalizes to nothing becomes agent.
Collision suggestions 3 by default, suffixes -2 through -9999 The base is shortened so the suffixed handle still fits in 80 characters.

Schedules

Enforced in src/routines/limits.ts, checked in src/routines/store.ts, src/routines/schedule.ts, and src/routines/validation.ts. Schedules run on Cloudflare only. Their error codes carry the word routine, which is what a schedule is called in the source.

Capacity

Limit Value At the limit
Active schedules per deployment 100 routine_active_limit, “This deployment has reached its active routine limit.”
Active schedules per channel 20 routine_channel_limit, “This channel has reached its active routine limit.”
Projected starts per schedule per day 300 routine_scheduled_capacity, “This schedule exceeds deployment capacity.”
Projected starts per deployment per day 600 routine_scheduled_capacity, raised when the new schedule’s projection pushes the deployment total past it.
Starts in any rolling 15 minutes 8 routine_cluster_capacity, at creation (“Too many routines run near that time.”) and at start time (“This deployment has reached its rolling routine start-rate limit.”).
Starts in a rolling 24 hours 610 routine_total_start_limit, “This deployment has reached its rolling routine start limit.”
Run-now starts in a rolling 24 hours 10 routine_run_now_limit, “This deployment has reached its rolling run-now limit.”
Concurrent runs per deployment 4 routine_concurrent_capacity, “This deployment has reached its active routine run limit.”
Concurrent runs per schedule 1 A second occurrence is not admitted while the first is running.

Cadence

Limit Value Note
Minimum interval between occurrences 5 minutes A tighter cadence is refused before the schedule is stored.
Occurrence projection horizon 370 days A schedule with no occurrence in that window is refused as routine_schedule_out_of_range.
Reservation lookahead 48 hours How far ahead occurrences are reserved against the rolling 15 minute ceiling.
Admission grace 15 minutes An occurrence older than the grace period is recorded as skipped, with reason admission_grace_expired or, for one-time work, missed_one_time.
Occurrence deadline 15 minutes The window in which a result may be delivered.
Due claims per heartbeat 25 The most occurrences one scheduler wake claims.
Admission lease, delivery lease 2 minutes each How long a claim is held before another attempt may take it.
Delivery retries on a Slack rate limit 1, and only when the retry-after is 30 seconds or less Nothing else is retried, because a repeat could post a private result twice.
Pending recovery delivery held open 24 hours A claimed recovery notice that never settles is recorded as unknown.

Fields

Field Limit
Name 80 code points and 320 bytes
Description 280 code points and 1,120 bytes
Task text 8,192 bytes
Schedule input as written 1,024 bytes
Normalized schedule JSON 4,096 bytes
Time zone 128 bytes, and a valid IANA name
Originating request text kept as provenance 8,192 bytes
Change key 1,024 bytes
Public error text 512 bytes

Retention

Record Kept for
Schedule metadata 365 days
Schedule actions 30 days
Pending confirmations 15 minutes to expiry, purged 24 hours later

Skill import

Enforced in src/config/skill-import.ts, which reads SKILL.md files from a GitHub repository.

Limit Value At the limit
Skill directories scanned 40 The extra directories are not read and the result reports capped: true, so the source can be narrowed with an @skill filter.
Characters kept from a description 1,024 Truncated, not rejected.
Characters kept from instructions 100,000 Truncated, not rejected.
Bytes read from one SKILL.md 512 KiB source_too_large, “GitHub skill document is too large to import safely.”
Bytes read from repository metadata 64 KiB source_too_large, “GitHub repository metadata is too large to import safely.”
Bytes read from the repository tree 16 MiB source_too_large, “GitHub repository tree is too large to import safely. Use a direct skill-directory URL.”
Bytes read from one directory listing page 4 MiB source_too_large, “GitHub skill directory is too large to import safely.”
Time for one GitHub request 10,000 ms The request is aborted.

The scan cap keeps one import under the Workers subrequest ceiling: resolution costs two subrequests plus one for every skill scanned.

Management requests

Enforced in src/management/contracts.ts and src/management/schemas.ts. One request is one atomic set of operations, whether it arrives from Admin, from Slack, or from the management MCP server.

Limit Value At the limit
Operations per request 1 to 25 “A management request must contain between 1 and 25 operations.”
Serialized request 128 KiB “The management request is too large.”
dependsOn entries per operation 25 Schema validation fails.
Operations a recipe may compile to 25 “The recipe compiles to more than 25 operations. Split it into smaller recipes.”

A request is also refused when its serialized form carries a control character or credential-like content, at any size: “Management operations cannot contain credentials or control characters.”

MCP client registration

Enforced in src/auth/mcp-oauth.ts, for dynamic client registration against the management MCP.

Limit Value At the limit
Client metadata document 16 KiB client_metadata_too_large, HTTP 413.
Registration request body 32 KiB request_too_large, HTTP 413.
client_name 120 characters, non-empty invalid_client_name.
redirect_uris 1 to 10 invalid_redirect_uri. A URI with a wildcard, credentials, or a fragment is refused, and plain HTTP is refused except on a loopback host.
response_types exactly ["code"] unsupported_response_type.
grant_types authorization_code, optionally with refresh_token unsupported_grant_type.
scope only chickpea:workspace invalid_scope.

Only public clients register: token_endpoint_auth_method must be none, and a request carrying jwks, jwks_uri, or token_endpoint_auth_signing_alg is refused as public_clients_only.

The coding sandbox

Enforced in src/config/sandbox-settings.ts, src/sandbox/session-cap.ts, and src/sandbox/egress-handler.ts. The coding sandbox is a Cloudflare container and is optional.

Limit Value At the limit
Container instance type standard-1 Fixed. It is not an operator choice.
Sessions per UTC calendar month operator setting; unset means uncapped The turn fails with sandbox_session_cap_reached, “The coding workspace monthly session limit has been reached.”
Session cap accepted in Admin 0 to 100,000, where 0 means no cap Values outside the range are refused. Settings → Coding sandbox → Advanced pre-fills 200 until the cap is saved.
Package registry hosts registry.npmjs.org, pypi.org, files.pythonhosted.org Any other host is denied. An unset allowlist permits all three; an explicit empty list blocks all three.
Methods allowed to those hosts GET, HEAD, POST Denied as method-denied.

A retry of the same durable turn reuses its reservation, so one turn cannot spend the monthly cap twice.

Telemetry delivery

Enforced in src/telemetry/client.ts. Product telemetry is advisory and never changes a customer-visible operation.

Limit Value At the limit
Serialized batch 32 KiB The batch is dropped without a request and without a retry.
Delivery time 5,000 ms The request is aborted.

Request bodies

Enforced by the bounded reader in src/security/request-body-limit.ts, which rejects a body whose declared Content-Length is malformed and stops reading once the actual bytes cross the limit. A body that is too large returns HTTP 413; a malformed Content-Length returns HTTP 400 on the Slack and MCP paths.

Route Limit Error
/channels/slack/events, /channels/slack/interactions 1 MiB 413
/mcp 1 MiB request_too_large
Admin mutation routes 1 MiB request_too_large
/webhooks/composio 256 KiB payload_too_large
Slack installation routes in Admin 64 KiB payload_too_large
/api/auth/* 32 KiB request_too_large
/auth/mcp/consent 16 KiB request_too_large
/setup/* 16 KiB request_too_large
/admin/setup, /admin/setup/*, /admin/recovery, /auth/slack/install/*, /auth/slack/oidc/*, /auth/slack/invite, /auth/slack/invite/* 8,192 bytes invalid_request
Team membership updates 2,048 bytes invalid_request, HTTP 400

On Node

Two groups above do not apply on Node. Schedules are Cloudflare only, and the conversational tool fails closed with routines_unavailable_on_target. The coding sandbox is a Cloudflare container, so its session cap and package registry allowlist have no effect; Node uses the standard sandbox. Every other limit on this page is enforced the same way on both targets.

What is not covered

Model context windows, provider rate limits, and provider token ceilings belong to the model provider, not to Chickpea. Slack’s own limits on message length, user groups, and API rate apply on top of these and are documented by Slack. Cloudflare’s platform limits on Workers, Durable Objects, and D1 apply on top of these and are documented by Cloudflare.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close