@felspar/sdk 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Felspar is a shared, versioned decision system for enterprise agents. A company's approved meaning, the evidence a decision needs and the decision itself travel together in a released Decision Pack. Agents ask Felspar for a decision, get a receipt they can verify, and act only on what Felspar decided.
4
4
 
5
- This package connects an agent to Felspar: an [Eve](https://github.com/vercel/eve) connection in two lines, a TypeScript client for the hosted Felspar API, an action gate that keeps an agent's tools from acting without a verified Felspar decision, and the agent skill for running any Felspar job. It runs on Node.js 24 or later, and its only dependency is `zod`. The SDK is a transport client: decisions and policy stay with the Felspar service and the released pack, and the SDK does not reimplement them.
5
+ This package connects an agent to Felspar: an [Eve](https://github.com/vercel/eve) connection in two lines, a TypeScript client for the hosted Felspar API, and an action gate that keeps an agent's tools from acting without a verified Felspar decision. It runs on Node.js 24 or later, and its only dependency is `zod`. The SDK is a transport client: decisions and policy stay with the Felspar service and the released pack, and the SDK does not reimplement them.
6
6
 
7
7
  The modules under `draft/` may change between minor versions while the API settles, before 1.0.
8
8
 
@@ -22,7 +22,9 @@ import { felsparConnection } from "@felspar/sdk/eve";
22
22
  export default defineMcpClientConnection(felsparConnection());
23
23
  ```
24
24
 
25
- The agent gets Felspar's `list_jobs`, `get_job_requirements`, `get_job_decision` and `check_output` tools and nothing else. The key is the agent's own, created on the Felspar web page (Workspace → Agents) and read from `FELSPAR_AGENT_KEY` when Eve connects; the endpoint is `FELSPAR_MCP_URL`, or production. Pass `{ url, agentKey, description }` to override them. Add the skill (below) so the agent knows the method.
25
+ The agent gets Felspar's `list_jobs`, `get_job_requirements`, `get_job_decision` and `check_output` tools and nothing else. The key is the agent's own, created on the Felspar web page (Workspace → Agents) and read from `FELSPAR_AGENT_KEY` when Eve connects; the endpoint is `FELSPAR_MCP_URL`, or production. Pass `{ url, agentKey, description }` to override them. The tools carry the method: `get_job_requirements` says what to gather and how, and each result says what to do next, so the agent needs no Felspar skill or prompt of its own.
26
+
27
+ Over MCP, `get_job_requirements` and `get_job_decision` answer compactly by default. The brief's `input` lists the arguments and a short `facts` example from the job's own questions. The decision keeps what the agent acts on, plus `executionObjectId`, the full `receipt`, the `context` capsule and `explanation.evidenceFreshUntil`, which is what the action gate records and verifies. `detail: "full"` returns the REST brief or result unchanged. The agent sends no execution ID: calling `get_job_decision` again with the same arguments within the same hour returns the decision already made, and `blocked` means that first call is still running. See [MCP tools](https://docs.felspar.ai/reference/mcp-tools).
26
28
 
27
29
  ## Hosted client
28
30
 
@@ -34,18 +36,23 @@ const felspar = createHostedFelsparClient({
34
36
  agentKey: process.env.FELSPAR_AGENT_KEY,
35
37
  });
36
38
 
37
- // What the job needs: questions, evidence rules, outcomes and their outputs.
38
- const job = await felspar.describeJob(releaseId, "classify-prospect");
39
+ // The jobs this agent key may run, by ID.
40
+ const { jobs } = await felspar.listJobs();
41
+
42
+ // What the job needs (questions, evidence rules, outcomes and their outputs),
43
+ // on the release Felspar runs for this key now.
44
+ const job = await felspar.describeCurrentJob("route-support-ticket");
45
+ const releaseId = job.release.releaseId;
39
46
 
40
47
  // Facts in, decision out. The release pin comes from the job description.
41
48
  const response = await felspar.resolveFacts(releaseId, {
42
- jobId: "classify-prospect",
49
+ jobId: "route-support-ticket",
43
50
  executionId: crypto.randomUUID(),
44
- entityId: "acme.com",
51
+ entityId: "48213",
45
52
  facts: {
46
- region: {
47
- text: "Acme is headquartered in Lyon, France.",
48
- source: { class: "crm", id: "acct-123", observedAt: new Date().toISOString() },
53
+ request_type: {
54
+ text: "I was charged twice for my March invoice.",
55
+ source: { class: "ticket-thread", id: "48213", observedAt: new Date().toISOString() },
49
56
  },
50
57
  },
51
58
  });
@@ -53,14 +60,15 @@ const response = await felspar.resolveFacts(releaseId, {
53
60
  if (response.status === "ready") {
54
61
  console.log(response.result?.outcome, response.result?.receipt);
55
62
  }
56
-
57
- // The jobs this agent key may run, by ID.
58
- const { jobs } = await felspar.listJobs();
59
63
  ```
60
64
 
65
+ `describeJob(releaseId, jobId)` describes a release you already know, such as one you pinned.
66
+
67
+ Facts can come straight from a system of record, with no agent in between: send each question's evidence as the source's own words (`text`, such as a ticket's body or an account record's "Plan: Business (monthly)") with where it came from (`source.class`, `source.id`, `source.observedAt`). Felspar classifies those words for answer-choice and yes/no questions; a bare label such as `{ value: "business" }` is refused with `label_needs_mapping`, because the released question decides what the words mean. Number and date questions take a typed `{ value }` (a date as `YYYY-MM-DD`). Only the job's own question keys are accepted (`unknown_question` otherwise).
68
+
61
69
  How a case is identified comes from the job's description (`identity`): send `entityId` for the record's own ID (`provided`), `identity` field values (`fields`), or nothing (`content`, and the first decision of an `issued` job). The result's `case` gives the case's `id` and `mode`; send `case.id` as `entityId` for every later decision on the same case. Results are typed (`FelsparJobResult`): `case`, `subject` with its `related` records, `escalation` (`id`, `trigger`, `why`) and `missing` for a gap.
62
70
 
63
- A refused request throws `FelsparRequestError` with the HTTP `status` and the service's `refusal` (its `error` code, where there is one a `fix`, and any `escalation` it names, such as for `attempt_limit_reached`).
71
+ A refused request throws `FelsparRequestError` with the HTTP `status` and the service's `refusal` (its `error` code, where there is one a `fix` and a `recovery` of `fix_input`, `retry` or `escalate`, and any `escalation` it names, such as for `attempt_limit_reached`).
64
72
 
65
73
  ## Action gate
66
74
 
@@ -148,16 +156,9 @@ Outside an agent framework, `checkAction({ rules, toolName, input, decisions, ve
148
156
 
149
157
  A Felspar receipt records what Felspar decided from the evidence it was given. It is not a factual, legal or security certification, and a passed output check means the text follows the released rules, not that it is true or approved to send.
150
158
 
151
- ## Agent skill
152
-
153
- The package ships the skill that teaches an agent the method for any Felspar job: get the requirements, gather exact evidence, get the decision, write and check what the decision asks for, and escalate with the company's next step.
154
-
155
- ```bash
156
- npx @felspar/sdk skill # writes agent/skills/felspar/SKILL.md
157
- npx @felspar/sdk skill .claude --force
158
- ```
159
+ ## Examples
159
160
 
160
- The directory defaults to `agent`, where an Eve agent keeps its skills; an existing copy is kept unless you pass `--force`.
161
+ [felspar-examples](https://github.com/orchidautomation/felspar-examples) has complete projects: an Eve agent, the same agent with email drafts behind the action gate, and a script that gets a decision with no agent.
161
162
 
162
163
  ## Documentation
163
164
 
@@ -2,7 +2,7 @@ import {
2
2
  denialText,
3
3
  entityIdOf,
4
4
  jobOf
5
- } from "./chunk-Y6KRRIQI.js";
5
+ } from "./chunk-ZHMUQJT2.js";
6
6
 
7
7
  // src/draft-action-gate-eve.ts
8
8
  function felsparGate(gate) {