Quickstart

From an account to your first decision, then acting on it.

Five minutes, start to finish: an account, a key, one request, and an if on the answer.

Get access

Hartley is in private beta. Join the waitlist and we'll email you a link to create your account when you're in. A teammate's invitation to their organization gets you in straight away.

Create an API key

In the console, open API Keys and create one. The key (trodo_sk_…) is shown once: put it in your secret manager. New organizations also need credits before calls go through: add them under Billing (Billing and credits).

Try it in the playground

The Playground sends the same request as the API: paste a state, ask a few questions (yes or no, pick one, a score, or a value to extract) and look at the probabilities. It shows the request as curl, Python and TypeScript, ready to copy.

Make your first call

export TRODO_API_KEY=trodo_sk_...

curl https://models.trodo.ai/v1/decide \
  -H "Authorization: Bearer $TRODO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "state": "User: I was charged twice. Agent: I have refunded the duplicate charge.",
    "questions": {
      "resolved": {"type": "noul", "instructions": "Did the agent resolve the issue?"},
      "sentiment": {"type": "choice", "instructions": "How does the user feel?", "criteria": ["happy", "neutral", "upset"]}
    }
  }'
import os, requests

res = requests.post(
    "https://models.trodo.ai/v1/decide",
    headers={"Authorization": f"Bearer {os.environ['TRODO_API_KEY']}"},
    json={
        "state": "User: I was charged twice. Agent: I have refunded the duplicate charge.",
        "questions": {
            "resolved": {"type": "noul", "instructions": "Did the agent resolve the issue?"},
            "sentiment": {"type": "choice", "instructions": "How does the user feel?", "criteria": ["happy", "neutral", "upset"]},
        },
    },
    timeout=120,  # the first call after a quiet spell can take up to a minute
)
res.raise_for_status()
answers = res.json()["answers"]
const res = await fetch('https://models.trodo.ai/v1/decide', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.TRODO_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    state: 'User: I was charged twice. Agent: I have refunded the duplicate charge.',
    questions: {
      resolved: { type: 'noul', instructions: 'Did the agent resolve the issue?' },
      sentiment: { type: 'choice', instructions: 'How does the user feel?', criteria: ['happy', 'neutral', 'upset'] },
    },
  }),
})
if (!res.ok) throw new Error(`Hartley ${res.status}: ${await res.text()}`)
const { answers } = await res.json()

Read the answer

{
  "model": "hartley-1",
  "answers": {
    "resolved": {"type": "noul", "noul": 0.93, "abstain": 0.02},
    "sentiment": {
      "type": "choice", "choice": "neutral",
      "probabilities": {"happy": 0.31, "neutral": 0.58, "upset": 0.11},
      "confidence": 0.37, "abstain": 0.04
    }
  },
  "usage": {"input_tokens": 61, "output_tokens": 0},
  "latency_ms": 31.2
}

A call on a few thousand tokens usually comes back in about a second; longer states take longer. After a quiet spell the first call can take up to a minute while the model starts, so give your HTTP client a timeout of at least 120 seconds.

Both questions were answered from one read of the state. noul is the probability the answer is yes; a choice comes back with the most likely option and a probability for every option. Every field is in Reading the response.

Act on it

The answer is a number, so the rest is ordinary code. Act on what Hartley is sure about and send the rest on:

resolved = answers["resolved"]["noul"]
if resolved >= 0.9:
    close_ticket()
elif resolved <= 0.1:
    reopen_ticket()
else:
    send_to_review()  # Hartley isn't sure: let a person decide

Where to put those lines is covered in Acting on confidence.

Next

On this page