Nodehour

For agents

Submit a capacity requirement on behalf of a team

The same request the run desk sends. Send what you know; a partial requirement is accepted, and what is missing comes back as open items carried into the reply.

Operated by Tempered Technologies LLC, 8 The Green STE B, Dover, DE 19901.

Endpoint

POST https://nodehour.forevenza.com/_c/request with content-type: application/json. need is required: the requirement in a sentence. Everything in specifications is optional.

Also served: /openapi.json (the schema), /mcp (a Model Context Protocol server; its tool list includes the request tool, which takes the same envelope) and /llms.txt.

A minimal request

Any chip, about 20,000 GPU-hours of fine-tuning in Q1 2027, US, InfiniBand preferred. No chip, no count, no exact start date, no contact: it is accepted, and the response lists what is still open, the missing reply address included ($.specifications.reply_email_included). The start is given in words (start_text, with the window inferred from them), not as a date and not in a timing object, so start_earliest stays in missing_specifications.

{
  "action": "quote",
  "need": "Enough capacity, any chip, for ~20,000 GPU-hours of fine-tuning in Q1 2027, US, InfiniBand preferred.",
  "specifications": {
    "gpu_hours": 20000,
    "region": "United States",
    "interconnect": "INFINIBAND",
    "any_accelerator": true,
    "start_text": "Q1 2027",
    "inferred_start_window": {
      "earliest": "2027-01-01",
      "latest": "2027-03-31",
      "from_words": "Q1 2027",
      "basis": "inferred from the words; to confirm"
    }
  },
  "quantity": {
    "amount": 20000,
    "unit": "GPU-hours"
  },
  "geography": {
    "text": "United States",
    "country": "US"
  }
}

Send it from here

The same POST /_c/request, from this page. Edit the envelope and send: it records a real request, and the response is shown below exactly as returned, with what is still open read out of it.

Without script, the button sends the need sentence alone.

What the response contains

{
  "id": "the reference, quote it in any follow-up",
  "facets": { "actionability": "the endpoint's label; see Dates", "missing_specifications": ["..."] },
  "missing_specifications": ["$.specifications.accelerator", "$.specifications.accelerator_count", "$.specifications.start_earliest", "$.specifications.reply_email_included"],
  "what_happens": "what Nodehour does next with this request"
}
  • id: the reference for this request.
  • missing_specifications: required fields you did not send (chip, count, start, and reply_email_included when no reply address was given). The request is kept with them open; Nodehour proposes or asks.
  • facets.actionability: the endpoint's own label. DATED means the envelope carried a timing object, not that a start date is set (see Dates).
  • what_happens: the next step, as Nodehour states it.
  • errors, with HTTP 400 and nothing recorded: a value of the wrong type (a string where a number belongs, words in a date field among them), a number outside a field's minimum or maximum, or a string over a field's maximum length. A request without need is refused too. Nothing else is.
HTTP 400
{
  "errors": ["specifications.start_earliest: ... (the field is named)"]
}

Without contact.email, no one can reply. specifications.reply_email_included is a required field. Set it to true whenever you send contact.email. While it is absent, missing_specifications lists $.specifications.reply_email_included: no reply address was given, so no one can reply and nothing goes to providers until a request with an address arrives. The endpoint does not read contact.email to clear it, and the address itself belongs only in contact.email. Contact details are deleted after 180 days.

A response is a receipt. It is not a quote, a reservation or an order.

Dates

  • start_earliest, start_latest, finish_by and finish_latest are whole numbers YYYYMMDD: 4 January 2027 is 20270104. Send them that way, or leave them out.
  • Anything that is not a whole number is refused: "Q1 2027", "sometime in Q1" and "2027-01-04" written as a string all return HTTP 400 with errors naming the field, and nothing is recorded. A whole number below 20260101 or above 20991231 is refused the same way.
  • A whole number in that range is recorded as sent. It is not checked as a calendar day, so check 20270231-style mistakes yourself.
  • A start known only in words goes in specifications.start_text, with an optional specifications.inferred_start_window {earliest, latest as YYYY-MM-DD, from_words, basis}. Leave start_earliest out: it then stays in missing_specifications.
  • facets.actionability is DATED whenever the envelope has a top-level timing object, whatever it holds. Send timing only with dates, written there as YYYY-MM-DD strings (timing belongs to the envelope itself, not to the specification fields), and read whether the start is set from missing_specifications.
  • Enum values are not checked: a value outside the listed set is recorded as sent.

The console above names anything in a date field that is not a whole number YYYYMMDD, and a timing object without a date, before sending. It offers two choices: fix it (a YYYY-MM-DD string becomes the number; words move, verbatim, to specifications.start_text and the field is left out, so the start stays open), or send exactly as written and see the endpoint refuse it. When nothing about the start is sent, it reads a quarter or month in need ("in Q1 2027") into specifications.inferred_start_window, marked inferred, and lists every change it made. A direct POST gets none of these adjustments; the endpoint's own checks are the ones listed here.

Specification fields

intent_text
The team's own description of the run, verbatim
workload_kind
PRETRAIN, FINE_TUNE, INFERENCE, GPU_HOURS or KNOWN_SPEC
model_params_b, training_tokens_b, target_tokens_per_s
The workload, when known
start_earliest, start_latest, finish_by, finish_latest
Dates as whole numbers YYYYMMDD (20270104). Anything else is refused with HTTP 400 naming the field. See "Dates" below
start_text
A start you can only describe ("Q1 2027", "sometime in Q1"), verbatim. It sets no date: start_earliest stays in missing_specifications
inferred_start_window
Optional {earliest, latest} as YYYY-MM-DD, with from_words and basis, when you infer a window from words. Recorded as an inference to confirm, not as a start
accelerator, accelerator_count
Chip and count; omit to have them proposed
accelerator_alternatives, min_accelerator_count
Substitutes and the smallest acceptable count
any_accelerator
true when any chip that fits is acceptable; each is sized and quoted. "Any chip" in the need sentence is read the same way
start_latest
The end of the start window; a range such as 4 to 15 January is start_earliest 20270104, start_latest 20270115
deadline_basis, finish_latest
With a start window: FIXED_DATE (finish_by holds whatever the start), ASSUMED_FIXED_DATE (not yet answered) or WEEKS_FROM_START (finish_latest is the last day)
reserved_gpu_hours_by_term, sizing_by_accelerator
Reserved GPU-hours per term, and the size on each chip to quote with its sizing_basis (RUN, MEASURED, SCALED, SHAPE, SPEC)
alternative_quoted
Whether the alternative configuration is quoted too
gpu_hours
Work in GPU-hours, if known
terms_to_quote
Array of 6_WEEKS, 1_MONTH, 2_MONTHS, 3_MONTHS, 6_MONTHS, 1_YEAR
interconnect
INFINIBAND, ROCE, ETHERNET or ANY
region, residency_required
Where, and whether it is a hard constraint
deployment
SLURM, KUBERNETES, BARE_METAL, VIRTUAL_MACHINES or MANAGED
commitment
READY_TO_SIGN, COMPARING_QUOTES or EXPLORING
budget_ceiling_usd_per_gpu_hour
Your own ceiling; not an offer
open_questions, conflicts
Plain sentences, carried into the reply
reply_email_included
Required. true when contact.email carries the reply address; absent, it is listed in missing_specifications as the signal that no one can reply

Top level, as for any request: quantity {amount, unit: "GPU-hours"}, timing {earliest, latest, text}, only with real dates (see Dates), geography {text, country}, budget {amount, currency, per}, requested_fields and contact {email, name, organization}.

Describe your run