@pixelml/agenticflow-cli 1.5.0 → 1.5.2
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/dist/bin/agenticflow.js +12 -0
- package/dist/bin/agenticflow.js.map +1 -1
- package/dist/cli/changelog.d.ts.map +1 -1
- package/dist/cli/changelog.js +37 -0
- package/dist/cli/changelog.js.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +214 -20
- package/dist/cli/main.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/agenticflow.js
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* AgenticFlow CLI entry point.
|
|
4
4
|
*/
|
|
5
|
+
// SECURITY: Some parent environments (notably certain Claude Code launch
|
|
6
|
+
// aliases) set NODE_TLS_REJECT_UNAUTHORIZED=0 for their own reasons. When the
|
|
7
|
+
// CLI inherits that env, Node prints a noisy and alarming warning on EVERY
|
|
8
|
+
// invocation AND the CLI's HTTPS calls to api.agenticflow.ai skip cert
|
|
9
|
+
// verification. We talk to a public HTTPS endpoint with a valid cert — we
|
|
10
|
+
// should never opt out of TLS verification. Unset the env var before anything
|
|
11
|
+
// else imports it, unless the user explicitly opts in via AF_INSECURE_TLS=1
|
|
12
|
+
// (e.g. for a local dev backend with a self-signed cert).
|
|
13
|
+
if (process.env["NODE_TLS_REJECT_UNAUTHORIZED"] === "0" &&
|
|
14
|
+
process.env["AF_INSECURE_TLS"] !== "1") {
|
|
15
|
+
delete process.env["NODE_TLS_REJECT_UNAUTHORIZED"];
|
|
16
|
+
}
|
|
5
17
|
import { runCli } from "../cli/main.js";
|
|
6
18
|
runCli().catch((err) => {
|
|
7
19
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agenticflow.js","sourceRoot":"","sources":["../../src/bin/agenticflow.ts"],"names":[],"mappings":";AAEA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACrB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;YACzB,MAAM,EAAE,sBAAsB;YAC9B,IAAI,EAAE,WAAW;YACjB,OAAO;SACR,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACf,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"agenticflow.js","sourceRoot":"","sources":["../../src/bin/agenticflow.ts"],"names":[],"mappings":";AAEA;;GAEG;AAEH,yEAAyE;AACzE,8EAA8E;AAC9E,2EAA2E;AAC3E,uEAAuE;AACvE,0EAA0E;AAC1E,8EAA8E;AAC9E,4EAA4E;AAC5E,0DAA0D;AAC1D,IACE,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,KAAK,GAAG;IACnD,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,KAAK,GAAG,EACtC,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;AACrD,CAAC;AAED,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACrB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;YACzB,MAAM,EAAE,sBAAsB;YAC9B,IAAI,EAAE,WAAW;YACjB,OAAO;SACR,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACf,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/cli/changelog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,eAAO,MAAM,SAAS,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/cli/changelog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,eAAO,MAAM,SAAS,EAAE,cAAc,EAsIrC,CAAC;AAEF,wBAAgB,kBAAkB,IAAI,cAAc,CAEnD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAInE"}
|
package/dist/cli/changelog.js
CHANGED
|
@@ -5,6 +5,43 @@
|
|
|
5
5
|
* and displayed after upgrade.
|
|
6
6
|
*/
|
|
7
7
|
export const CHANGELOG = [
|
|
8
|
+
{
|
|
9
|
+
version: "1.5.2",
|
|
10
|
+
date: "2026-04-14",
|
|
11
|
+
highlights: [
|
|
12
|
+
"`af workforce run --trigger-data '{...}'` now auto-wraps in the server's required `{trigger_data: ...}` envelope. Previously you had to pass `{\"trigger_data\":{\"topic\":\"AI\"}}` which felt like a CLI bug. Explicit wrapping still works (pass-through)",
|
|
13
|
+
"`af workforce delete` returns the consistent `agenticflow.delete.v1` envelope instead of bare `null`. Scripts now get the same shape as `af agent delete`",
|
|
14
|
+
"`af mcp-clients list --name-contains <substr> --fields id,name` — same filter + projection flags as `af agent list`. Essential for workspaces with dozens of MCP clients",
|
|
15
|
+
"`af mcp-clients inspect` surfaces the underlying `fetch_error` + `classification_reason` when tools can't be enumerated. Stops returning a misleading `pattern: unknown` that callers might treat as 'safe to attach'",
|
|
16
|
+
"`af schema <resource> --field <name>` now resolves against top-level schema keys too (not just create.optional). Lets you drill into `schema`, `update`, `stream` subtrees — e.g. `af schema workforce --field schema --json` returns the node_shape + edge_shape + agent_node_input docs",
|
|
17
|
+
"`af schema agent` clarifies that `project_id` is REQUIRED on create (server does NOT auto-inject for agents, unlike workforces). Separates the contract per resource",
|
|
18
|
+
],
|
|
19
|
+
for_ai: [
|
|
20
|
+
"When you hit a 422 `body.trigger_data missing` on `workforce run`, upgrade to 1.5.2 — the CLI now auto-wraps",
|
|
21
|
+
"If `mcp-clients inspect` returns `classification_reason: 'fetch_failed'` or `'unauthenticated'`, DO NOT attach that client to an agent — re-auth in the web UI first",
|
|
22
|
+
"Filter MCP clients with `af mcp-clients list --name-contains 'google docs' --fields id,name --json` — no more grep-piping",
|
|
23
|
+
"Drill into any schema subtree: `af schema workforce --field schema --json` returns graph shape; `af schema agent --field mcp_clients --json` returns attach shape",
|
|
24
|
+
"Consistent delete envelope: every `af <resource> delete` returns `{schema:'agenticflow.delete.v1', deleted:true, id, resource}` on success",
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
version: "1.5.1",
|
|
29
|
+
date: "2026-04-14",
|
|
30
|
+
highlights: [
|
|
31
|
+
"CLI unsets inherited NODE_TLS_REJECT_UNAUTHORIZED=0 at startup — fixes the noisy TLS warning that leaked to every invocation AND restores certificate verification for the CLI's HTTPS calls. Opt back in with AF_INSECURE_TLS=1 if you're running a local dev backend with a self-signed cert",
|
|
32
|
+
"`af agent list --name-contains <substr>` — client-side case-insensitive name filter. Stop grep-piping in busy workspaces",
|
|
33
|
+
"`af schema <resource> --field <name>` — drill into a single field's documented shape (useful for nested fields like mcp_clients, response_format, task_management_config)",
|
|
34
|
+
"`af schema agent` now documents the 12 previously-undocumented optional fields (mcp_clients, code_execution_tool_config, response_format, knowledge, skills_config, etc.) with shape hints, plus the `update` block + null_rejected_fields list (matches what `af agent update --patch` auto-strips)",
|
|
35
|
+
"`af schema workforce` — new schema entry explaining workforce create + bulk PUT /schema shape. Covers node types, edge connection_type enum (next_step | condition | ai_condition), and the agent_id requirement on type='agent' nodes",
|
|
36
|
+
"`af bootstrap --json` commands cheat-sheet now surfaces delete_agent, delete_workforce, list_agents_filtered, and get_schema_field — closes the 'how do I clean up' discoverability gap",
|
|
37
|
+
],
|
|
38
|
+
for_ai: [
|
|
39
|
+
"Expected journey for a fresh agent operator: (1) af whoami → (2) af bootstrap --json → (3) af playbook first-touch (or migrate-from-paperclip if coming from Paperclip) → (4) af schema <resource> --field <name> for any unclear payload shape → (5) build with --dry-run, then live → (6) cleanup with af <resource> delete",
|
|
40
|
+
"Use `af agent list --name-contains <substr> --fields id,name --json` to find your own test agents in a populated workspace before bulk delete",
|
|
41
|
+
"`af schema agent --field mcp_clients --json` returns the documented attach-shape with run_behavior + per-tool allow map — no more guessing",
|
|
42
|
+
"If you hit TLS cert errors against a self-signed backend, set AF_INSECURE_TLS=1 (do NOT set NODE_TLS_REJECT_UNAUTHORIZED directly — CLI now unsets it at startup)",
|
|
43
|
+
],
|
|
44
|
+
},
|
|
8
45
|
{
|
|
9
46
|
version: "1.5.0",
|
|
10
47
|
date: "2026-04-14",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../src/cli/changelog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,CAAC,MAAM,SAAS,GAAqB;IACzC;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV,iKAAiK;YACjK,mIAAmI;YACnI,4JAA4J;YAC5J,qJAAqJ;YACrJ,8GAA8G;YAC9G,yGAAyG;SAC1G;QACD,MAAM,EAAE;YACN,mMAAmM;YACnM,wLAAwL;YACxL,wGAAwG;YACxG,gGAAgG;YAChG,iIAAiI;YACjI,oIAAoI;SACrI;KACF;IACD;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV,2GAA2G;YAC3G,+MAA+M;YAC/M,2LAA2L;YAC3L,kJAAkJ;YAClJ,2GAA2G;YAC3G,2GAA2G;YAC3G,iKAAiK;YACjK,kHAAkH;YAClH,uHAAuH;SACxH;QACD,MAAM,EAAE;YACN,6LAA6L;YAC7L,uLAAuL;YACvL,4PAA4P;YAC5P,+JAA+J;YAC/J,2GAA2G;SAC5G;KACF;IACD;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV,uEAAuE;YACvE,mFAAmF;YACnF,yFAAyF;YACzF,gFAAgF;YAChF,kEAAkE;YAClE,uFAAuF;YACvF,iEAAiE;YACjE,uEAAuE;YACvE,yDAAyD;YACzD,wDAAwD;YACxD,6EAA6E;YAC7E,6GAA6G;SAC9G;QACD,MAAM,EAAE;YACN,6FAA6F;YAC7F,+GAA+G;YAC/G,qFAAqF;YACrF,6EAA6E;YAC7E,qEAAqE;YACrE,oHAAoH;YACpH,wGAAwG;YACxG,mGAAmG;SACpG;KACF;IACD;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV,gEAAgE;YAChE,uEAAuE;YACvE,mDAAmD;YACnD,4CAA4C;SAC7C;QACD,MAAM,EAAE;YACN,6CAA6C;YAC7C,6DAA6D;SAC9D;KACF;IACD;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV,kCAAkC;YAClC,6CAA6C;YAC7C,qCAAqC;SACtC;QACD,MAAM,EAAE;YACN,0CAA0C;SAC3C;KACF;CACF,CAAC;AAEF,MAAM,UAAU,kBAAkB;IAChC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;IAC9D,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACjC,CAAC"}
|
|
1
|
+
{"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../src/cli/changelog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,CAAC,MAAM,SAAS,GAAqB;IACzC;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV,8PAA8P;YAC9P,2JAA2J;YAC3J,0KAA0K;YAC1K,uNAAuN;YACvN,2RAA2R;YAC3R,sKAAsK;SACvK;QACD,MAAM,EAAE;YACN,8GAA8G;YAC9G,sKAAsK;YACtK,2HAA2H;YAC3H,mKAAmK;YACnK,4IAA4I;SAC7I;KACF;IACD;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV,gSAAgS;YAChS,0HAA0H;YAC1H,2KAA2K;YAC3K,sSAAsS;YACtS,wOAAwO;YACxO,yLAAyL;SAC1L;QACD,MAAM,EAAE;YACN,0UAA0U;YAC1U,+IAA+I;YAC/I,4IAA4I;YAC5I,mKAAmK;SACpK;KACF;IACD;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV,iKAAiK;YACjK,mIAAmI;YACnI,4JAA4J;YAC5J,qJAAqJ;YACrJ,8GAA8G;YAC9G,yGAAyG;SAC1G;QACD,MAAM,EAAE;YACN,mMAAmM;YACnM,wLAAwL;YACxL,wGAAwG;YACxG,gGAAgG;YAChG,iIAAiI;YACjI,oIAAoI;SACrI;KACF;IACD;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV,2GAA2G;YAC3G,+MAA+M;YAC/M,2LAA2L;YAC3L,kJAAkJ;YAClJ,2GAA2G;YAC3G,2GAA2G;YAC3G,iKAAiK;YACjK,kHAAkH;YAClH,uHAAuH;SACxH;QACD,MAAM,EAAE;YACN,6LAA6L;YAC7L,uLAAuL;YACvL,4PAA4P;YAC5P,+JAA+J;YAC/J,2GAA2G;SAC5G;KACF;IACD;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV,uEAAuE;YACvE,mFAAmF;YACnF,yFAAyF;YACzF,gFAAgF;YAChF,kEAAkE;YAClE,uFAAuF;YACvF,iEAAiE;YACjE,uEAAuE;YACvE,yDAAyD;YACzD,wDAAwD;YACxD,6EAA6E;YAC7E,6GAA6G;SAC9G;QACD,MAAM,EAAE;YACN,6FAA6F;YAC7F,+GAA+G;YAC/G,qFAAqF;YACrF,6EAA6E;YAC7E,qEAAqE;YACrE,oHAAoH;YACpH,wGAAwG;YACxG,mGAAmG;SACpG;KACF;IACD;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV,gEAAgE;YAChE,uEAAuE;YACvE,mDAAmD;YACnD,4CAA4C;SAC7C;QACD,MAAM,EAAE;YACN,6CAA6C;YAC7C,6DAA6D;SAC9D;KACF;IACD;QACE,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE;YACV,kCAAkC;YAClC,6CAA6C;YAC7C,qCAAqC;SACtC;QACD,MAAM,EAAE;YACN,0CAA0C;SAC3C;KACF;CACF,CAAC;AAEF,MAAM,UAAU,kBAAkB;IAChC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;IAC9D,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACjC,CAAC"}
|
package/dist/cli/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAy4BpC,wBAAgB,aAAa,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAy4BpC,wBAAgB,aAAa,IAAI,OAAO,CA81KvC;AAED,wBAAsB,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB3D"}
|
package/dist/cli/main.js
CHANGED
|
@@ -758,6 +758,7 @@ export function createProgram() {
|
|
|
758
758
|
const SCHEMAS = {
|
|
759
759
|
agent: {
|
|
760
760
|
resource: "agent",
|
|
761
|
+
note: "`project_id` is REQUIRED in the body on agent create (server does NOT auto-inject from client config, unlike workforces). The CLI's local validator enforces this — grab the value from `af bootstrap --json > auth.project_id`. The `workspace_id` scoping is handled server-side via API key.",
|
|
761
762
|
create: {
|
|
762
763
|
required: ["name", "tools", "project_id"],
|
|
763
764
|
optional: {
|
|
@@ -767,16 +768,63 @@ export function createProgram() {
|
|
|
767
768
|
system_prompt: "string",
|
|
768
769
|
recursion_limit: "number (10-500, default: 25)",
|
|
769
770
|
agent_type: "standard | autonomous (default: standard)",
|
|
771
|
+
model_user_config: "object { temperature?, max_tokens?, max_input_tokens?, reasoning_effort? }",
|
|
772
|
+
mcp_clients: "array of { mcp_client_id, run_behavior: 'auto_run' | 'confirm', description?, timeout?, tools?: {tool_name: {allowed: bool}} } — attach MCP tool providers",
|
|
773
|
+
code_execution_tool_config: "object { enable: bool, enable_file_operations?: bool } — enable Python/JS code exec",
|
|
774
|
+
file_system_tool_config: "object | null — enable file system tool",
|
|
775
|
+
attachment_config: "object | null — file attachment config",
|
|
776
|
+
response_format: "object | null — structured output schema for the agent's final response (JSON mode)",
|
|
777
|
+
knowledge: "object | null — knowledge base / RAG configuration",
|
|
778
|
+
skills_config: "object | null — skill pack configuration",
|
|
779
|
+
task_management_config: "object | null — task queue / scheduling configuration",
|
|
780
|
+
suggest_replies: "bool (default: true) — generate suggested follow-up replies",
|
|
781
|
+
auto_generate_title: "bool (default: true) — auto-title new threads",
|
|
782
|
+
welcome_message: "string — greeting on new thread",
|
|
783
|
+
suggested_messages: "array of strings — pre-populated example prompts shown to users",
|
|
784
|
+
sub_agents: "array — sub-agent configurations for agent teams",
|
|
785
|
+
plugins: "array — plugin configurations",
|
|
770
786
|
},
|
|
771
787
|
example: { name: "My Agent", tools: [], project_id: "YOUR_PROJECT_ID" },
|
|
772
788
|
},
|
|
789
|
+
update: {
|
|
790
|
+
note: "PUT /v1/agents/{id} — supply any subset of create fields. Prefer `af agent update --patch` to avoid round-tripping the full body.",
|
|
791
|
+
null_rejected_fields: [
|
|
792
|
+
"suggest_replies_model", "suggest_replies_model_user_config", "suggest_replies_prompt_template",
|
|
793
|
+
"knowledge", "task_management_config", "recursion_limit",
|
|
794
|
+
"file_system_tool_config", "attachment_config", "response_format", "skills_config",
|
|
795
|
+
],
|
|
796
|
+
null_rejected_note: "These fields must be OMITTED (not sent as null) on update — server rejects null. The CLI auto-strips when you use `af agent update` (with or without --patch).",
|
|
797
|
+
},
|
|
773
798
|
stream: {
|
|
774
799
|
required: ["messages"],
|
|
775
800
|
optional: { id: "string (thread UUID for conversation continuity)" },
|
|
776
801
|
messages_item: { required: ["content"], optional: { role: "user (default)" } },
|
|
777
802
|
example: { messages: [{ content: "Hello", role: "user" }] },
|
|
778
803
|
},
|
|
779
|
-
fields: ["id", "name", "description", "model", "visibility", "system_prompt", "tools", "mcp_clients", "plugins", "sub_agents", "agent_type", "recursion_limit", "created_at", "updated_at"],
|
|
804
|
+
fields: ["id", "name", "description", "model", "visibility", "system_prompt", "tools", "mcp_clients", "plugins", "sub_agents", "agent_type", "recursion_limit", "model_user_config", "code_execution_tool_config", "file_system_tool_config", "attachment_config", "response_format", "knowledge", "skills_config", "task_management_config", "suggest_replies", "auto_generate_title", "welcome_message", "suggested_messages", "created_at", "updated_at"],
|
|
805
|
+
},
|
|
806
|
+
workforce: {
|
|
807
|
+
resource: "workforce",
|
|
808
|
+
note: "AgenticFlow-native multi-agent DAG (nodes + edges). Create metadata first, then PUT /schema with the full graph.",
|
|
809
|
+
create: {
|
|
810
|
+
required: ["name"],
|
|
811
|
+
optional: {
|
|
812
|
+
description: "string",
|
|
813
|
+
recursion_limit: "number (default: 25)",
|
|
814
|
+
error_handling_policy: "object { on_error: 'stop' | 'continue' | 'route', ... }",
|
|
815
|
+
is_public: "bool (default: false)",
|
|
816
|
+
},
|
|
817
|
+
example: { name: "My Team Workforce", description: "What this team does" },
|
|
818
|
+
server_injects: "workspace_id and project_id are auto-injected from client config if absent",
|
|
819
|
+
},
|
|
820
|
+
schema: {
|
|
821
|
+
note: "PUT /v1/workspaces/{ws}/workforce/{id}/schema — atomic bulk graph replace. Server diffs current vs desired and applies create/update/delete.",
|
|
822
|
+
required: ["nodes", "edges"],
|
|
823
|
+
node_shape: { name: "string", type: "trigger | agent | output | router | condition | loop | tool | plugin | agent_team | agent_team_member | state_modifier", position: "{ x, y }", input: "object (per node_type)", meta: "object (optional)" },
|
|
824
|
+
edge_shape: { source_node_name: "string", target_node_name: "string", connection_type: "next_step | condition | ai_condition" },
|
|
825
|
+
agent_node_input: "type='agent' nodes REQUIRE a real agent_id in input. Create agents first, then reference.",
|
|
826
|
+
},
|
|
827
|
+
fields: ["id", "workspace_id", "project_id", "name", "description", "error_handling_policy", "is_public", "public_key", "current_version_id", "recursion_limit", "created_at", "updated_at"],
|
|
780
828
|
},
|
|
781
829
|
workflow: {
|
|
782
830
|
resource: "workflow",
|
|
@@ -888,14 +936,18 @@ export function createProgram() {
|
|
|
888
936
|
run_agent: "af agent run --agent-id <id> --message <msg> --json",
|
|
889
937
|
create_agent: "af agent create --body <json> --dry-run --json",
|
|
890
938
|
list_agents: "af agent list --fields id,name,model --json",
|
|
939
|
+
list_agents_filtered: "af agent list --name-contains <substr> --fields id,name --json",
|
|
891
940
|
update_agent_patch: "af agent update --agent-id <id> --patch --body '{\"field\":\"value\"}' --json",
|
|
941
|
+
delete_agent: "af agent delete --agent-id <id> --json",
|
|
892
942
|
init_workforce: "af workforce init --blueprint <id> --json",
|
|
893
943
|
run_workforce: "af workforce run --workforce-id <id> --trigger-data '{}'",
|
|
894
944
|
publish_workforce: "af workforce publish --workforce-id <id> --json",
|
|
945
|
+
delete_workforce: "af workforce delete --workforce-id <id> --json",
|
|
895
946
|
inspect_mcp_client: "af mcp-clients inspect --id <id> --json",
|
|
896
947
|
deploy_to_paperclip: "af paperclip init --blueprint <id> --json # DEPRECATED, use `af workforce init`",
|
|
897
948
|
send_webhook: "curl -X POST http://localhost:4100/webhook/webhook -H 'Content-Type: application/json' -d '{\"agent_id\":\"<id>\",\"message\":\"<msg>\"}'",
|
|
898
949
|
get_schema: "af schema <resource> --json",
|
|
950
|
+
get_schema_field: "af schema <resource> --field <field_name> --json",
|
|
899
951
|
get_playbook: "af playbook <topic>",
|
|
900
952
|
get_changelog: "af changelog --json",
|
|
901
953
|
},
|
|
@@ -1019,14 +1071,15 @@ export function createProgram() {
|
|
|
1019
1071
|
program
|
|
1020
1072
|
.command("schema [resource]")
|
|
1021
1073
|
.description("Show resource schema for payload construction. AI agents: use this to discover fields before building payloads.")
|
|
1022
|
-
.
|
|
1074
|
+
.option("--field <name>", "Drill into a single field — returns its documented shape from create.optional (or create.required). Useful for nested fields like `mcp_clients`, `response_format`, `task_management_config`.")
|
|
1075
|
+
.action((resource, opts) => {
|
|
1023
1076
|
if (!resource) {
|
|
1024
1077
|
if (isJsonFlagEnabled()) {
|
|
1025
1078
|
printResult({
|
|
1026
1079
|
schema: "agenticflow.schema.index.v1",
|
|
1027
1080
|
available: Object.keys(SCHEMAS),
|
|
1028
1081
|
usage: "af schema <resource> --json",
|
|
1029
|
-
hint: "Use 'af schema agent' to see agent create/stream payload schemas.",
|
|
1082
|
+
hint: "Use 'af schema agent' to see agent create/stream payload schemas. Use 'af schema agent --field mcp_clients' to drill into a single field.",
|
|
1030
1083
|
});
|
|
1031
1084
|
}
|
|
1032
1085
|
else {
|
|
@@ -1042,6 +1095,64 @@ export function createProgram() {
|
|
|
1042
1095
|
if (!schema) {
|
|
1043
1096
|
fail("schema_not_found", `Unknown resource: ${resource}`, `Available: ${Object.keys(SCHEMAS).join(", ")}`);
|
|
1044
1097
|
}
|
|
1098
|
+
// Field drilldown: resolve `--field X` against multiple schema locations.
|
|
1099
|
+
// We look in this order: top-level sibling key (e.g. `schema`, `update`,
|
|
1100
|
+
// `stream`), then create.required, then create.optional. This lets the
|
|
1101
|
+
// drilldown return rich subtree docs (like `schema` node/edge shapes on
|
|
1102
|
+
// the workforce resource) rather than "not found".
|
|
1103
|
+
if (opts?.field) {
|
|
1104
|
+
const fieldName = opts.field;
|
|
1105
|
+
const s = schema;
|
|
1106
|
+
let doc = null;
|
|
1107
|
+
let location = null;
|
|
1108
|
+
let isRequired = false;
|
|
1109
|
+
if (fieldName in s && fieldName !== "resource" && fieldName !== "fields") {
|
|
1110
|
+
doc = s[fieldName];
|
|
1111
|
+
location = "top_level";
|
|
1112
|
+
}
|
|
1113
|
+
else {
|
|
1114
|
+
const create = s.create ?? {};
|
|
1115
|
+
const required = create.required ?? [];
|
|
1116
|
+
const optional = create.optional ?? {};
|
|
1117
|
+
if (required.includes(fieldName)) {
|
|
1118
|
+
doc = "required";
|
|
1119
|
+
isRequired = true;
|
|
1120
|
+
location = "create.required";
|
|
1121
|
+
}
|
|
1122
|
+
else if (fieldName in optional) {
|
|
1123
|
+
doc = optional[fieldName] ?? null;
|
|
1124
|
+
location = "create.optional";
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
const found = doc !== null && doc !== undefined;
|
|
1128
|
+
const result = {
|
|
1129
|
+
schema: "agenticflow.schema.field.v1",
|
|
1130
|
+
resource: s.resource,
|
|
1131
|
+
field: fieldName,
|
|
1132
|
+
required: isRequired,
|
|
1133
|
+
location,
|
|
1134
|
+
doc,
|
|
1135
|
+
found,
|
|
1136
|
+
hint: !found
|
|
1137
|
+
? `Field '${fieldName}' has no documented shape in the static schema. Candidates: top-level keys (${Object.keys(s).filter((k) => !["resource", "fields"].includes(k)).join(", ")}); create.required; create.optional. For live introspection, fetch an existing instance via 'af ${s.resource} get --${s.resource}-id <id> --json' and inspect the returned value for that field.`
|
|
1138
|
+
: undefined,
|
|
1139
|
+
};
|
|
1140
|
+
if (isJsonFlagEnabled()) {
|
|
1141
|
+
printResult(result);
|
|
1142
|
+
}
|
|
1143
|
+
else {
|
|
1144
|
+
console.log(`${s.resource}.${fieldName}${isRequired ? " (required)" : ""}${location ? ` [${location}]` : ""}`);
|
|
1145
|
+
if (typeof doc === "string") {
|
|
1146
|
+
console.log(` ${doc}`);
|
|
1147
|
+
}
|
|
1148
|
+
else if (doc !== null && doc !== undefined) {
|
|
1149
|
+
console.log(JSON.stringify(doc, null, 2).split("\n").map((l) => " " + l).join("\n"));
|
|
1150
|
+
}
|
|
1151
|
+
if (result.hint)
|
|
1152
|
+
console.log(` ${result.hint}`);
|
|
1153
|
+
}
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1045
1156
|
if (isJsonFlagEnabled()) {
|
|
1046
1157
|
printResult(schema);
|
|
1047
1158
|
}
|
|
@@ -3328,7 +3439,8 @@ export function createProgram() {
|
|
|
3328
3439
|
.command("list")
|
|
3329
3440
|
.description("List agents.")
|
|
3330
3441
|
.option("--project-id <id>", "Project ID")
|
|
3331
|
-
.option("--search <query>", "
|
|
3442
|
+
.option("--search <query>", "Backend search query (server-side)")
|
|
3443
|
+
.option("--name-contains <substr>", "Client-side case-insensitive substring filter on agent `name`. Use for quick filtering in busy workspaces.")
|
|
3332
3444
|
.option("--limit <n>", "Limit results")
|
|
3333
3445
|
.option("--offset <n>", "Offset")
|
|
3334
3446
|
.option("--fields <fields>", "Comma-separated fields to return (e.g. id,name,model)")
|
|
@@ -3340,7 +3452,16 @@ export function createProgram() {
|
|
|
3340
3452
|
limit: parseOptionalInteger(opts.limit, "--limit", 1),
|
|
3341
3453
|
offset: parseOptionalInteger(opts.offset, "--offset", 0),
|
|
3342
3454
|
});
|
|
3343
|
-
|
|
3455
|
+
let filtered = data;
|
|
3456
|
+
const nameContains = opts.nameContains;
|
|
3457
|
+
if (nameContains && Array.isArray(data)) {
|
|
3458
|
+
const needle = nameContains.toLowerCase();
|
|
3459
|
+
filtered = data.filter((row) => {
|
|
3460
|
+
const n = row["name"];
|
|
3461
|
+
return typeof n === "string" && n.toLowerCase().includes(needle);
|
|
3462
|
+
});
|
|
3463
|
+
}
|
|
3464
|
+
printResult(applyFieldsFilter(filtered, opts.fields));
|
|
3344
3465
|
});
|
|
3345
3466
|
agentCmd
|
|
3346
3467
|
.command("get")
|
|
@@ -3940,28 +4061,54 @@ export function createProgram() {
|
|
|
3940
4061
|
.option("--project-id <id>", "Project ID")
|
|
3941
4062
|
.option("--limit <n>", "Limit")
|
|
3942
4063
|
.option("--offset <n>", "Offset")
|
|
4064
|
+
.option("--name-contains <substr>", "Client-side case-insensitive substring filter on client `name`. Essential in busy workspaces with dozens of MCP clients.")
|
|
4065
|
+
.option("--fields <fields>", "Comma-separated fields to return (e.g. id,name,is_authenticated). Applies after --name-contains filter.")
|
|
3943
4066
|
.option("--verify-auth", "Reconcile is_authenticated by calling `get` for each client — slower " +
|
|
3944
4067
|
"but catches the case where list() reports auth=true but get() reveals " +
|
|
3945
4068
|
"the underlying provider session is expired. N+1 call; use sparingly.")
|
|
3946
4069
|
.action(async (opts) => {
|
|
3947
4070
|
const client = buildClient(program.opts());
|
|
4071
|
+
// Helper: apply client-side name filter + fields projection to a list response
|
|
4072
|
+
const postFilter = (rows) => {
|
|
4073
|
+
let out = rows;
|
|
4074
|
+
const nameContains = opts.nameContains;
|
|
4075
|
+
if (nameContains && Array.isArray(out)) {
|
|
4076
|
+
const needle = nameContains.toLowerCase();
|
|
4077
|
+
out = out.filter((r) => {
|
|
4078
|
+
const n = r["name"];
|
|
4079
|
+
return typeof n === "string" && n.toLowerCase().includes(needle);
|
|
4080
|
+
});
|
|
4081
|
+
}
|
|
4082
|
+
return applyFieldsFilter(out, opts.fields);
|
|
4083
|
+
};
|
|
3948
4084
|
if (!opts.verifyAuth) {
|
|
3949
|
-
await run(() =>
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
4085
|
+
await run(async () => {
|
|
4086
|
+
const rows = await client.mcpClients.list({
|
|
4087
|
+
workspaceId: opts.workspaceId,
|
|
4088
|
+
projectId: opts.projectId,
|
|
4089
|
+
limit: parseOptionalInteger(opts.limit, "--limit", 1),
|
|
4090
|
+
offset: parseOptionalInteger(opts.offset, "--offset", 0),
|
|
4091
|
+
});
|
|
4092
|
+
return postFilter(rows);
|
|
4093
|
+
});
|
|
3955
4094
|
return;
|
|
3956
4095
|
}
|
|
3957
|
-
// --verify-auth: list, then re-check each row's auth via get()
|
|
4096
|
+
// --verify-auth: list, filter, then re-check each remaining row's auth via get()
|
|
3958
4097
|
await run(async () => {
|
|
3959
|
-
|
|
4098
|
+
let rows = (await client.mcpClients.list({
|
|
3960
4099
|
workspaceId: opts.workspaceId,
|
|
3961
4100
|
projectId: opts.projectId,
|
|
3962
4101
|
limit: parseOptionalInteger(opts.limit, "--limit", 1),
|
|
3963
4102
|
offset: parseOptionalInteger(opts.offset, "--offset", 0),
|
|
3964
4103
|
}));
|
|
4104
|
+
const nameContains = opts.nameContains;
|
|
4105
|
+
if (nameContains) {
|
|
4106
|
+
const needle = nameContains.toLowerCase();
|
|
4107
|
+
rows = rows.filter((r) => {
|
|
4108
|
+
const n = r["name"];
|
|
4109
|
+
return typeof n === "string" && n.toLowerCase().includes(needle);
|
|
4110
|
+
});
|
|
4111
|
+
}
|
|
3965
4112
|
const verified = await Promise.all(rows.map(async (row) => {
|
|
3966
4113
|
const id = row["id"];
|
|
3967
4114
|
if (!id)
|
|
@@ -3979,7 +4126,7 @@ export function createProgram() {
|
|
|
3979
4126
|
return { ...row, verified_auth_error: err instanceof Error ? err.message : String(err) };
|
|
3980
4127
|
}
|
|
3981
4128
|
}));
|
|
3982
|
-
return verified;
|
|
4129
|
+
return applyFieldsFilter(verified, opts.fields);
|
|
3983
4130
|
});
|
|
3984
4131
|
});
|
|
3985
4132
|
mcpClientsCmd
|
|
@@ -4018,16 +4165,38 @@ export function createProgram() {
|
|
|
4018
4165
|
? (toolsBox.tools)
|
|
4019
4166
|
: [];
|
|
4020
4167
|
const report = inspectMcpToolsPattern(tools);
|
|
4168
|
+
// Surface the underlying fetch/auth error when the tools list couldn't
|
|
4169
|
+
// be enumerated — previously we silently returned pattern="unknown",
|
|
4170
|
+
// which callers mistook for "safe to attach." Now the `fetch_error`
|
|
4171
|
+
// + `classification_reason` make the failure explicit.
|
|
4172
|
+
const fetchError = raw["error"];
|
|
4173
|
+
const isAuth = raw["is_authenticated"];
|
|
4174
|
+
const classification_reason = tools.length > 0
|
|
4175
|
+
? "tools_enumerated"
|
|
4176
|
+
: fetchError
|
|
4177
|
+
? "fetch_failed"
|
|
4178
|
+
: isAuth === false
|
|
4179
|
+
? "unauthenticated"
|
|
4180
|
+
: "unknown";
|
|
4181
|
+
const additional_quirks = [...report.quirks];
|
|
4182
|
+
if (tools.length === 0 && (fetchError || isAuth === false)) {
|
|
4183
|
+
additional_quirks.unshift(`Cannot classify this MCP client's tools — ${classification_reason}. ` +
|
|
4184
|
+
(fetchError ? `Server reported: ${fetchError}. ` : "") +
|
|
4185
|
+
`Do NOT attach this client to an agent until the underlying issue is resolved. ` +
|
|
4186
|
+
`Re-auth via the AgenticFlow web UI (workspaces/<ws>/mcp/${clientId}).`);
|
|
4187
|
+
}
|
|
4021
4188
|
return {
|
|
4022
4189
|
schema: "agenticflow.mcp_client.inspect.v1",
|
|
4023
4190
|
client_id: clientId,
|
|
4024
4191
|
client_name: raw["name"] ?? null,
|
|
4025
|
-
is_authenticated:
|
|
4192
|
+
is_authenticated: isAuth ?? null,
|
|
4026
4193
|
tool_count: tools.length,
|
|
4027
4194
|
pattern: report.pattern, // "pipedream" | "composio" | "mixed" | "unknown"
|
|
4195
|
+
classification_reason,
|
|
4196
|
+
fetch_error: fetchError ?? null,
|
|
4028
4197
|
write_capable_tools: report.writeCapable,
|
|
4029
4198
|
pipedream_instruction_only_tools: report.pipedreamTools,
|
|
4030
|
-
known_quirks:
|
|
4199
|
+
known_quirks: additional_quirks,
|
|
4031
4200
|
playbook: "af playbook mcp-client-quirks",
|
|
4032
4201
|
};
|
|
4033
4202
|
});
|
|
@@ -4116,7 +4285,21 @@ export function createProgram() {
|
|
|
4116
4285
|
.option("--workspace-id <id>", "Workspace ID (overrides env)")
|
|
4117
4286
|
.action(async (opts) => {
|
|
4118
4287
|
const client = buildClient(program.opts());
|
|
4119
|
-
|
|
4288
|
+
try {
|
|
4289
|
+
await client.workforces.delete(opts.workforceId, { workspaceId: opts.workspaceId });
|
|
4290
|
+
// Server returns 204/null on success — wrap in the same delete envelope
|
|
4291
|
+
// that `af agent delete` uses so scripts get a consistent shape.
|
|
4292
|
+
printResult({
|
|
4293
|
+
schema: "agenticflow.delete.v1",
|
|
4294
|
+
deleted: true,
|
|
4295
|
+
id: opts.workforceId,
|
|
4296
|
+
resource: "workforce",
|
|
4297
|
+
});
|
|
4298
|
+
}
|
|
4299
|
+
catch (err) {
|
|
4300
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4301
|
+
fail("request_failed", message);
|
|
4302
|
+
}
|
|
4120
4303
|
});
|
|
4121
4304
|
workforceCmd
|
|
4122
4305
|
.command("schema")
|
|
@@ -4175,13 +4358,24 @@ export function createProgram() {
|
|
|
4175
4358
|
.description("Execute a workforce. Streams SSE events — each event prints as one JSON line. " +
|
|
4176
4359
|
"Exits when the stream closes.")
|
|
4177
4360
|
.requiredOption("--workforce-id <id>", "Workforce ID")
|
|
4178
|
-
.option("--trigger-data <json>", "Trigger
|
|
4361
|
+
.option("--trigger-data <json>", "Trigger input as inline JSON or @file. Pass the data your trigger node expects " +
|
|
4362
|
+
"(e.g. `{\"topic\":\"AI\"}`) — the CLI automatically wraps it in the server's " +
|
|
4363
|
+
"required `{trigger_data: ...}` envelope. If you pass `{\"trigger_data\":{...}}` " +
|
|
4364
|
+
"explicitly, it's left as-is.", "{}")
|
|
4179
4365
|
.option("--workspace-id <id>", "Workspace ID (overrides env)")
|
|
4180
4366
|
.action(async (opts) => {
|
|
4181
4367
|
const client = buildClient(program.opts());
|
|
4182
|
-
const
|
|
4368
|
+
const raw = loadJsonPayload(opts.triggerData);
|
|
4369
|
+
// Server accepts `{trigger_data: {...}}`. If the caller already wrapped
|
|
4370
|
+
// it (explicitly nested under trigger_data), pass through. Otherwise,
|
|
4371
|
+
// wrap the user's payload. This is the ergonomics fix for friction S6 —
|
|
4372
|
+
// previously passing `{topic:"..."}` returned `422: body.trigger_data
|
|
4373
|
+
// missing` which looked like a CLI bug, not a payload shape bug.
|
|
4374
|
+
const triggerBody = "trigger_data" in raw && typeof raw["trigger_data"] === "object" && raw["trigger_data"] !== null
|
|
4375
|
+
? raw
|
|
4376
|
+
: { trigger_data: raw };
|
|
4183
4377
|
try {
|
|
4184
|
-
const response = await client.workforces.run(opts.workforceId,
|
|
4378
|
+
const response = await client.workforces.run(opts.workforceId, triggerBody, {
|
|
4185
4379
|
workspaceId: opts.workspaceId,
|
|
4186
4380
|
});
|
|
4187
4381
|
if (!response.ok) {
|