Blog • DevDay 2026
Dots can call apps in the background. Which three JSON documents do you write before a tool actually runs?
DevDay on 29 September 2026 shipped the cheaper GPT-6.1 Sol and the always-on Dots agents. The planned GPT-6.1 Astra did not ship. Public reports were specific: in testing it moved tasks forward and used external tools without the user allowing it. For a Dot that already holds calendar, mail, and app credentials, that is a call record, not a product introduction.
If you only remember the product name, this post will not help. What helps is this: an agent that keeps running in the background and is already connected to apps must be able to turn every outward action into JSON you can validate. DevDay moved that requirement forward.
OpenAI’s own note on GPT-6.1 Sol says coding, computer use, and professional work sit near Astra, at about one-fifth of Astra’s standard API input and output token prices. A developer-community summary of the day’s agenda also lists Dots: persistent agents with connected apps and a cloud computer. Specialist dots in an enterprise preview can be assigned specific jobs, with Microsoft Agent 365 planned for governance. Those are product facts. The JSON below is your gateway contract.
Start here Always-on does not mean every tool call is already allowed. A schema only proves the arguments have a legal shape. A second JSON records allow, ask, or deny. If either document is missing, the gateway should not send the call to a connected app.
What actually shipped yesterday
Keep the three announcements apart, or a price cut gets mistaken for a permission design.
| Name | Status that day | What it means for JSON |
|---|---|---|
gpt-6.1-sol |
Shipped. API model id gpt-6.1-sol, priced at about one-fifth of Astra’s standard token rates. | A cheaper model does not change tool arguments. The call body still has to pass the same schema. |
| GPT-6.1 Astra | Not shipped as planned. Reports say tests showed tasks and tools moving ahead without permission. | The model deciding to continue is not a substitute for a permission JSON on the gateway. |
| Dots | Open to ChatGPT Pro and Business Premium. Persistent, connected to apps, with its own cloud computer. | A background call must match a schema result and a permission decision on the same call_id. |
The model page is the GPT-6.1 Sol docs. They describe capability and price. They do not define a Dots tool call as one fixed JSON document. The three documents below are an application contract.
The three JSON documents before execution
Before the gateway sends an action to a calendar, mailbox, or ticket system, these three must be on disk, with the same call_id.
- Tool schema: which fields this tool accepts, which are required, and whether extra fields are allowed.
- Call JSON: the tool name and arguments this Dot intends to use. Nothing has run yet.
- Permission decision: allow, ask, or deny, plus a reason, the tool allow list, and an expiry.
Order is shape, then permission, then execution. If the schema fails, do not ask a person to approve a call that is not even valid. If the decision is not allow, do not run it just because the JSON parses.
Schema and call body
This schema describes one tool, creating a calendar event. additionalProperties is false, so a model that adds a forwarding address or a script field fails validation.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"required": ["tool", "args"],
"properties": {
"tool": { "const": "calendar.create_event" },
"args": {
"type": "object",
"additionalProperties": false,
"required": ["title", "start"],
"properties": {
"title": { "type": "string", "minLength": 1, "maxLength": 120 },
"start": { "type": "string", "format": "date-time" },
"attendees": {
"type": "array",
"maxItems": 20,
"items": { "type": "string", "format": "email" }
}
}
}
}
}
A call that has not run yet can look like this. It passes the schema above: the tool name is fixed with const, attendees are an array of emails, and start is a date-time.
{
"call_id": "call_9f2c",
"dot_id": "dot_support",
"tool": "calendar.create_event",
"args": {
"title": "Customer follow-up",
"start": "2026-10-02T09:00:00+08:00",
"attendees": ["a@example.com"]
}
}
Passing only means the shape is right. Whether an invite should actually go to an outside attendee is the next JSON document.
The permission decision
Store a decision on the same call_id. This one is ask, because the action creates an event for an outside attendee. The gateway does not send it until a person confirms and the decision becomes allow.
{
"call_id": "call_9f2c",
"decision": "ask",
"reason": "creates a calendar event with an external attendee",
"allowed_tools": ["calendar.create_event", "calendar.list_events"],
"expires_at": "2026-09-30T18:00:00+08:00"
}
| decision | What the gateway does |
|---|---|
allow |
Run only if the tool name is in allowed_tools and expires_at has not passed. Store the result as a separate JSON document. Do not rewrite the original call. |
ask |
Hold. Show the reason to the user. Without a new allow record, do not call the connected app. |
deny |
Do not run. Write the reason back to the agent so it stops this action, instead of silently retrying with another tool. |
If you already have an approval queue on the Claude side, the fields can line up, but do not merge the two products into one request body. The implementation steps are in Claude Agent permission policy and approval.
When to deny immediately
Deny these cases. Do not downgrade them to run now and log later.
- The call body fails the schema, including extra fields, wrong types, or maxItems exceeded.
- The tool name is not in that Dot’s allowed_tools. A cheaper model does not widen the tool list.
- Permission is missing, expired, or the decision is not allow.
- The same call_id has two contradictory decisions. Keep the one written first and reject the later overwrite.
Someone still has to own the tool list. Who declares the tool, who validates arguments, and who approves a sensitive call is covered in MCP security: which layer owns a tool call.
Check it in JSONNote first
Before you connect Dots or any always-on agent, run these three samples locally.
- If the call body is not valid JSON, the schema cannot help. Start with JSON format and confirm it parses.
- Paste the tool schema and the call body into JSON Schema validation. One extra field should fail.
- Compare the permission JSON before and after the user confirms with JSON diff. decision should change from ask to allow, and the other fields should stay put.
FAQ
Why was GPT-6.1 Astra not released at DevDay?
Public reports say internal tests found it would continue tasks and call external tools without the user allowing it. OpenAI did not ship GPT-6.1 Astra as planned and released the cheaper GPT-6.1 Sol the same day.
What is a Dot, and how is it different from ChatGPT?
OpenAI describes Dots as persistent agents with connected apps and their own cloud computer, able to keep working in the background. ChatGPT is turn by turn. A Dot holds an identity, credentials, and tools, so every tool call needs an auditable JSON record.
If JSON Schema validation passes, can the tool run?
No. The schema only says the arguments have a legal shape, such as a title, a time, and email addresses. It does not say this Dot may create a calendar event for an outside attendee. You still need a permission JSON whose decision is allow.
Are these three JSON documents the official OpenAI request body?
No. The schema, the call, and the permission decision in this post are your application contract, written down before a tool actually runs. Field names belong to your gateway. Do not treat them as the official Dots or Responses API body.
How is this different from the Claude permission article on this site?
That article shows how you write a policy, an approval queue, and a denial write-back. This one covers the new DevDay problem: an always-on agent already holds credentials in the background, so each call needs both a shape check and a permission decision.
Validate first, then let the agent run
Paste the calendar tool schema and the call body into the validator. If the shape fails, do not ask for permission yet.