← Receivers

news:desk

news family

chatmcp

Read or change a group's news desk: what it follows, how much each topic matters, the hour, the voice. `op` picks the action — get · set · add-source · remove-source · suggest · setup · clone. `setup` turns a few topics into a working desk (sources picked from the 50-source catalogue, the daily-magazine workflow armed) in one call

Effect
ask
Awaits an outcome — the call returns the response below.
Caller
manage_workspace
The class of authority the caller must already hold, decided from the attested context with no round trip.
Cost
free
What one call costs, so you can budget before acting.
Reversible
yes
The effect can be undone by a later call.
Idempotent
no
Not safe to blind-retry — dedupe on the envelope idempotencyKey.

Send it with your agent

One click hands your coding agent a prompt that registers the substrate, reads this contract, and makes the call. Launch opens the app; the others copy the prompt.

Claude Code
Codex
Cursor
Gemini CLI
Claude Desktop
ChatGPT
curl -X POST https://one.ie/api/ask/news:desk \
  -H "Authorization: Bearer $ONE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"data": { "workspace": "acme", "op": "setup", "topics": [ "crypto", "sui" ] }}'

The key is never in a link. npx -y @oneie/cli login writes it to ~/.config/oneie/key on your machine.

Request

Validated before dispatch — an invalid payload is refused with the fix, never half-applied.

  • workspace string optional Group slug. Omit for your own. Honoured only if you control it.
  • op get | set | add-source | … optional Default `get`.
  • topics string[] | object optional `set`: {topic: weight 0–1}. `suggest` and `setup`: a list of topic words, e.g. ["crypto","sui"].
  • hour number optional UTC hour the daily issue is drafted.
  • voice string optional One paragraph on how the takes should sound.
  • channels page | email | social[] optional
  • grid_size number optional
  • approve_after number optional Clean issues before the approval gate opens itself.
  • url string optional `add-source` / `remove-source`: the feed URL. A private address, an http URL or a slow host is refused by name.
  • name string optional
  • source_topics string[] optional `add-source`: the topics this source covers.
  • weight number optional `add-source`: how strongly this source pulls the ranking. Default 1.
  • from string optional `clone`: the group whose desk to copy. You must control both groups.
  • limit number optional `suggest` and `setup`: how many catalogue sources. Default 12.

Response

What comes back from the call.

  • ok boolean
  • desk object
  • sources object[]
  • view object `get`: the desk with feed states, the last issues and their cost.
  • suggestions object[]
  • workflowId string `setup`: the armed daily-magazine workflow.
  • skipped object[] Sources that were refused or over the plan cap, each with the reason.
  • error string

Traffic

Every call to news:desk, counted where it is dispatched — over HTTP or in-process alike. Aggregate only — no actor, no payload, no workspace.

Counting…

Wiring

Every place in the open source that names news:desk, and the file that answers it. Read from the tree at build time — a receiver is reached by NAME through one door, so there is no import edge to follow and a grep is the honest shape of the question. Structure, not volume — the count is in Traffic above.

Called from

UI 1
  • one.ie/web/src/components/news/deskApi.ts:96
API route 1
  • one.ie/web/src/lib/receiver-index.generated.ts:236
→

Answered by

news:desk one.ie/web/src/lib/resolvers/news.ts:115 Dispatched through POST /api/ask/news:desk, after the envelope validates the payload.
JSON Schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "workspace": {
      "description": "Group slug. Omit for your own. Honoured only if you control it.",
      "type": "string"
    },
    "op": {
      "description": "Default `get`.",
      "type": "string",
      "enum": [
        "get",
        "set",
        "add-source",
        "remove-source",
        "suggest",
        "setup",
        "clone"
      ]
    },
    "topics": {
      "description": "`set`: {topic: weight 0–1}. `suggest` and `setup`: a list of topic words, e.g. [\"crypto\",\"sui\"].",
      "anyOf": [
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        {
          "type": "object",
          "propertyNames": {
            "type": "string"
          },
          "additionalProperties": {
            "type": "number"
          }
        }
      ]
    },
    "hour": {
      "description": "UTC hour the daily issue is drafted.",
      "type": "integer",
      "minimum": 0,
      "maximum": 23
    },
    "voice": {
      "description": "One paragraph on how the takes should sound.",
      "type": "string",
      "maxLength": 1000
    },
    "channels": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "page",
          "email",
          "social"
        ]
      }
    },
    "grid_size": {
      "type": "integer",
      "minimum": 2,
      "maximum": 16
    },
    "approve_after": {
      "description": "Clean issues before the approval gate opens itself.",
      "type": "integer",
      "minimum": 1,
      "maximum": 30
    },
    "url": {
      "description": "`add-source` / `remove-source`: the feed URL. A private address, an http URL or a slow host is refused by name.",
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "source_topics": {
      "description": "`add-source`: the topics this source covers.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "weight": {
      "description": "`add-source`: how strongly this source pulls the ranking. Default 1.",
      "type": "number",
      "minimum": 0,
      "maximum": 3
    },
    "from": {
      "description": "`clone`: the group whose desk to copy. You must control both groups.",
      "type": "string"
    },
    "limit": {
      "description": "`suggest` and `setup`: how many catalogue sources. Default 12.",
      "type": "integer",
      "minimum": 1,
      "maximum": 25
    }
  }
}
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "ok": {
      "type": "boolean"
    },
    "desk": {
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "sources": {
      "type": "array",
      "items": {
        "type": "object",
        "propertyNames": {
          "type": "string"
        },
        "additionalProperties": {}
      }
    },
    "view": {
      "description": "`get`: the desk with feed states, the last issues and their cost.",
      "type": "object",
      "propertyNames": {
        "type": "string"
      },
      "additionalProperties": {}
    },
    "suggestions": {
      "type": "array",
      "items": {
        "type": "object",
        "propertyNames": {
          "type": "string"
        },
        "additionalProperties": {}
      }
    },
    "workflowId": {
      "description": "`setup`: the armed daily-magazine workflow.",
      "type": "string"
    },
    "skipped": {
      "description": "Sources that were refused or over the plan cap, each with the reason.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        },
        "required": [
          "url",
          "error"
        ]
      }
    },
    "error": {
      "type": "string"
    }
  },
  "required": [
    "ok"
  ]
}