You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
authored
fix(attio): give Create Task and Create or Update Record a static prop set (#21768)
* fix(attio): give Create Task and Create or Update Record a static prop set
Both actions built their inputs in additionalProps(), driven by reloadProps,
and both fetched remote data to do it. An MCP tool is registered with a single
static JSON Schema, so props that only exist after a reload never reach an
agent.
Create Task generated a targetObject/targetRecordId pair per linked record,
counted by numberOfLinkedRecords. It now takes linkedRecords, a list of JSON
objects, and reports a malformed or incomplete entry instead of sending a
half-built link.
Create or Update Record fetched the object's writable attributes and emitted a
prop per attribute. It now takes values, one object of attribute slug to value,
the shape the Salesforce and HubSpot conversions settled on. objectId and
matchingAttribute keep their remote options and their dependency on each other;
only the reload goes.
That also fixes what run() sent: it collected everything on his that was not
a known prop, so the action's own methods travelled to Attio as attribute
values. values is an explicit prop now, so only values are sent.
* fix(attio): name the input when Values will not parse
A malformed JSON string reached the caller as a raw SyntaxError, while the
sibling create-task action says which linked record is wrong. Values is parsed
once, before the request is built, and a parse failure now says so.
* fix(attio): validate Values object + reconcile create-update-record description
- create-update-record: reject non-object Values (null, arrays, scalars) with a
clear ConfigurationError before the upsert, instead of passing them to the API.
- Description: swap the misleading "a deal" example (deals are filtered out of the
object options because upsert needs a unique matching attribute they lack) for
"a company", and note that objects without a unique attribute aren't available.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(attio): AI-optimize action descriptions + mark components optimized
agent-audit raised attio from ~52 to 100/100. All 8 action descriptions now
carry behavioral guidance ("Use when…"/"Returns…"), a concrete worked example,
and cross-references to lookup actions (e.g. delete-list-entry → List List ID
Options; update-person → Get Record). Marked every action file and the app file
with `// x-pd-ai: optimized`. No behavior change — descriptions/metadata only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(attio): add List Records action
Adds an AI-optimized list/search action for records of any object (people,
companies, deals, custom) — wraps the existing records query endpoint. Fills the
gap where the toolset could create/update/get records but not enumerate them,
which forced agents to (mis)use the record-id option loader as a backdoor.
Discoverable Object prop, bounded Limit (1–500), Offset paging with follow-up
guidance, and an additive Fields projection to trim payload.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(attio): reference List Records in record-id prop descriptions + version bumps
- All record-id-based prop descriptions (app-level recordId, get-record, update-person
Person ID/Company ID, create-person Company ID, create-note Parent Record ID) now
point the agent to the **List Records** action to look up record IDs.
- Version bumps required by the shared app-file change + new List Records action:
6 actions and all 10 sources patched; package.json 0.6.0 -> 0.7.0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore(attio): keep package.json at 0.6.0
The 0.6.0 bump already on this PR covers the component changes; revert the
extra 0.7.0 bump.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Michelle Bergeron <michelle.bergeron@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: michelle0927 <michelle0927@users.noreply.github.com>
Copy file name to clipboardExpand all lines: components/attio/actions/create-note/create-note.mjs
+4-3Lines changed: 4 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,11 @@
1
+
// x-pd-ai: optimized
1
2
importattiofrom"../../attio.app.mjs";
2
3
3
4
exportdefault{
4
5
key: "attio-create-note",
5
6
name: "Create Note",
6
-
description: "Creates a new note for a given record. The note will be linked to the specified record. [See the documentation](https://developers.attio.com/reference/post_v2-notes)",
7
-
version: "0.0.6",
7
+
description: "Create a plaintext note attached to a record (person, company, deal, or any object). Use when you want to log context on a record. Set **Parent Object**, **Parent Record ID**, **Title**, and **Content**. Example: Parent Object `people`, Parent Record ID `891dcbfc-9141-415d-9b2a-2238a6cc012d`, Title `Intro call`, Content `Discussed the Q3 rollout timeline`. Returns the created note with its id. [See the documentation](https://developers.attio.com/reference/post_v2-notes)",
8
+
version: "0.0.7",
8
9
annotations: {
9
10
destructiveHint: false,
10
11
openWorldHint: true,
@@ -39,7 +40,7 @@ export default {
39
40
}),
40
41
],
41
42
label: "Parent Record ID",
42
-
description: "The ID of the parent record the note belongs to",
43
+
description: "The ID of the parent record the note belongs to. Use the **List Records** action to look up record IDs.",
Copy file name to clipboardExpand all lines: components/attio/actions/create-person/create-person.mjs
+4-3Lines changed: 4 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -1,11 +1,12 @@
1
+
// x-pd-ai: optimized
1
2
importattiofrom"../../attio.app.mjs";
2
3
importconstantsfrom"../../common/constants.mjs";
3
4
4
5
exportdefault{
5
6
key: "attio-create-person",
6
7
name: "Create Person",
7
-
description: "Creates a new person. [See the documentation](https://developers.attio.com/reference/post_v2-objects-people-records).",
8
-
version: "0.0.4",
8
+
description: "Create a new person record in Attio. Use when adding a contact. Set any of the person fields (name, email, job title, phone, socials) and optionally link a company by its record id. Example: First Name `Ada`, Last Name `Lovelace`, Email `ada@example.com`, Job Title `Analyst`. Returns the created person record with its id. [See the documentation](https://developers.attio.com/reference/post_v2-objects-people-records).",
9
+
version: "0.0.5",
9
10
annotations: {
10
11
destructiveHint: false,
11
12
openWorldHint: true,
@@ -82,7 +83,7 @@ export default {
82
83
},
83
84
companyId: {
84
85
label: "Company ID",
85
-
description: "The ID of the company to associate with the person.",
86
+
description: "The ID of the company to associate with the person. Use the **List Records** action (object `companies`) to look up company record IDs.",
description: "Creates a new task. [See the documentation](https://docs.attio.com/rest-api/endpoint-reference/tasks/create-a-task)",
9
-
version: "0.0.4",
8
+
description: "Create a task in Attio with content, a deadline, completion state, optional assignees, and optional linked records. Use when you need a follow-up or to-do. Example: Content `Email the signed contract to Ada`, Deadline `2026-09-01T17:00:00Z`, Is Completed `false`. Returns the created task with its id. [See the documentation](https://docs.attio.com/rest-api/endpoint-reference/tasks/create-a-task)",
9
+
version: "0.1.0",
10
10
annotations: {
11
11
destructiveHint: false,
12
12
openWorldHint: true,
@@ -39,102 +39,50 @@ export default {
39
39
"workspaceMemberId",
40
40
],
41
41
},
42
-
numberOfLinkedRecords: {
43
-
type: "integer",
44
-
label: "Number Of Linked Records",
45
-
description: "The number of linked records to generate. Defaults to 1.",
46
-
default: 1,
47
-
reloadProps: true,
42
+
linkedRecords: {
43
+
type: "string[]",
44
+
label: "Linked Records",
45
+
description: "Records to link to the task. Each entry is a JSON object naming the object type and the record, e.g. `{ \"target_object\": \"companies\", \"target_record_id\": \"891dcbfc-9141-415d-9b2a-2238a6cc012d\" }`. `target_object` accepts `companies`, `people`, `users`, `workspaces` or `deals`.",
description: "Creates or updates a specific record such as a person or a deal. If the record already exists, it's updated. Otherwise, a new record is created. [See the documentation](https://developers.attio.com/reference/put_v2-objects-object-records)",
9
-
version: "0.0.6",
9
+
description: "Creates or updates a specific record such as a person or a company. If a record with the same matching attribute already exists, it's updated; otherwise a new record is created. Objects without a unique attribute to match on (e.g. deals) are not available here. Example: Object `companies`, Matching Attribute `domains`, Values `{ \"domains\": [\"acme.com\"], \"name\": \"Acme\" }`. Returns the created or updated record with its id. [See the documentation](https://developers.attio.com/reference/put_v2-objects-object-records)",
description: "Attribute slug to value pairs for the record, e.g. `{ \"name\": \"Ada Lovelace\", \"email_addresses\": [\"ada@example.test\"] }`. Include the matching attribute among them. [See the attributes endpoint](https://developers.attio.com/reference/get_v2-target-identifier-attributes) for what a given object accepts.",
78
41
},
79
42
},
80
43
asyncrun({ $ }){
81
44
const{
82
45
attio,
83
46
objectId,
84
47
matchingAttribute,
85
-
...values
48
+
values,
86
49
}=this;
87
50
51
+
letparsedValues;
52
+
try{
53
+
parsedValues=typeofvalues==="string"
54
+
? JSON.parse(values)
55
+
: values;
56
+
}catch(error){
57
+
thrownewConfigurationError(`Values is not valid JSON: ${error.message}`);
58
+
}
59
+
60
+
if(
61
+
parsedValues===null
62
+
||typeofparsedValues!=="object"
63
+
||Array.isArray(parsedValues)
64
+
){
65
+
thrownewConfigurationError(
66
+
"Values must be a JSON object of attribute slug to value pairs (not a list, null, or a single value).",
Copy file name to clipboardExpand all lines: components/attio/actions/delete-list-entry/delete-list-entry.mjs
+3-2Lines changed: 3 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,11 @@
1
+
// x-pd-ai: optimized
1
2
importattiofrom"../../attio.app.mjs";
2
3
3
4
exportdefault{
4
5
key: "attio-delete-list-entry",
5
6
name: "Delete List Entry",
6
-
description: "Deletes an existing entry from a specific list. [See the documentation](https://developers.attio.com/reference/delete_v2-lists-list-entries-entry-id)",
7
-
version: "0.0.6",
7
+
description: "Delete an entry from a list (this removes the record from the list, not the underlying record itself). Destructive — confirm the entry before deleting. Use **List List ID Options** to find a **List ID**, then choose the **Entry ID** to remove. Example: List ID `33ebdbe9-e529-47c9-b894-0ba25e9c15c0`, Entry ID `2e6e29ea-c4e9-4f4b-9b1e-7f2c1a0d9c11`. Returns the API confirmation. [See the documentation](https://developers.attio.com/reference/delete_v2-lists-list-entries-entry-id)",
Copy file name to clipboardExpand all lines: components/attio/actions/get-record/get-record.mjs
+4-3Lines changed: 4 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,11 @@
1
+
// x-pd-ai: optimized
1
2
importattiofrom"../../attio.app.mjs";
2
3
3
4
exportdefault{
4
5
key: "attio-get-record",
5
6
name: "Get Record",
6
-
description: "Retrieves the record with the specified ID. [See the documentation](https://docs.attio.com/rest-api/endpoint-reference/records/get-a-record)",
7
-
version: "0.0.3",
7
+
description: "Retrieve a single record by its ID from a given object (people, companies, deals, or a custom object). Use when you have a record's id and need its attribute values. Example: Object `people`, Record ID `891dcbfc-9141-415d-9b2a-2238a6cc012d`. Returns the record with its attribute values. [See the documentation](https://docs.attio.com/rest-api/endpoint-reference/records/get-a-record)",
8
+
version: "0.0.4",
8
9
annotations: {
9
10
destructiveHint: false,
10
11
openWorldHint: true,
@@ -20,7 +21,7 @@ export default {
20
21
],
21
22
},
22
23
recordId: {
23
-
description: "The identifier of the record to retrieve.",
24
+
description: "The identifier of the record to retrieve. Use the **List Records** action to look up record IDs.",
Copy file name to clipboardExpand all lines: components/attio/actions/list-list-id-options/list-list-id-options.mjs
+3-2Lines changed: 3 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,11 @@
1
+
// x-pd-ai: optimized
1
2
importattiofrom"../../attio.app.mjs";
2
3
3
4
exportdefault{
4
5
key: "attio-list-list-id-options",
5
6
name: "List List ID Options",
6
-
description: "Retrieves available options for the List ID field.",
7
-
version: "0.0.1",
7
+
description: "List the workspace's lists as {value, label} options, to discover a **List ID** to pass to other actions (e.g. Delete List Entry). Use when you need a list's id and don't have it. Takes no input. Example: call with no arguments; returns e.g. `[{ \"value\": \"33ebdbe9-e529-47c9-b894-0ba25e9c15c0\", \"label\": \"Hot Leads\" }]`. [See the documentation](https://developers.attio.com/reference/get_v2-lists)",
0 commit comments