Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 198 additions & 0 deletions docs/api-reference/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1628,6 +1628,130 @@
"x-codegen-request-body-name" : "payload"
}
},
"/space/{space_id}/experience_confirmations" : {
"get" : {
"description" : "Get all experience confirmations in a space with cursor-based pagination",
"parameters" : [ {
"description" : "Space ID",
"in" : "path",
"name" : "space_id",
"required" : true,
"schema" : {
"format" : "uuid",
"type" : "string"
}
}, {
"description" : "Limit of confirmations to return, default 20. Max 200.",
"in" : "query",
"name" : "limit",
"schema" : {
"type" : "integer"
}
}, {
"description" : "Cursor for pagination. Use the cursor from the previous response to get the next page.",
"in" : "query",
"name" : "cursor",
"schema" : {
"type" : "string"
}
}, {
"description" : "Order by created_at descending if true, ascending if false (default false)",
"in" : "query",
"name" : "time_desc",
"schema" : {
"type" : "boolean"
}
} ],
"responses" : {
"200" : {
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/_space__space_id__experience_confirmations_get_200_response"
}
}
},
"description" : "OK"
}
},
"security" : [ {
"BearerAuth" : [ ]
} ],
"summary" : "Get experience confirmations",
"tags" : [ "space" ],
"x-code-samples" : [ {
"label" : "Python",
"lang" : "python",
"source" : "from acontext import AcontextClient\n\nclient = AcontextClient(api_key='sk_project_token')\n\n# Get unconfirmed experiences\nexperiences = client.spaces.get_unconfirmed_experiences(\n space_id='space-uuid',\n limit=20,\n time_desc=True\n)\nfor experience in experiences.items:\n print(f\"{experience.id}: {experience.experience_data}\")\n\n# If there are more, use the cursor for pagination\nif experiences.has_more:\n next_experiences = client.spaces.get_unconfirmed_experiences(\n space_id='space-uuid',\n limit=20,\n cursor=experiences.next_cursor\n )\n"
}, {
"label" : "JavaScript",
"lang" : "javascript",
"source" : "import { AcontextClient } from '@acontext/acontext';\n\nconst client = new AcontextClient({ apiKey: 'sk_project_token' });\n\n// Get unconfirmed experiences\nconst experiences = await client.spaces.getUnconfirmedExperiences('space-uuid', {\n limit: 20,\n timeDesc: true\n});\nfor (const experience of experiences.items) {\n console.log(`${experience.id}: ${JSON.stringify(experience.experience_data)}`);\n}\n\n// If there are more, use the cursor for pagination\nif (experiences.hasMore) {\n const nextExperiences = await client.spaces.getUnconfirmedExperiences('space-uuid', {\n limit: 20,\n cursor: experiences.nextCursor\n });\n}\n"
} ]
}
},
"/space/{space_id}/experience_confirmations/{experience_id}" : {
"patch" : {
"description" : "Confirm an experience confirmation. If save is false, delete the row. If save is true, get the data first (TODO: process data), then delete the row.",
"parameters" : [ {
"description" : "Space ID",
"in" : "path",
"name" : "space_id",
"required" : true,
"schema" : {
"format" : "uuid",
"type" : "string"
}
}, {
"description" : "Experience Confirmation ID",
"in" : "path",
"name" : "experience_id",
"required" : true,
"schema" : {
"format" : "uuid",
"type" : "string"
}
} ],
"requestBody" : {
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/handler.ConfirmExperienceReq"
}
}
},
"description" : "Confirmation request with save flag",
"required" : true
},
"responses" : {
"200" : {
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/_space__space_id__experience_confirmations__experience_id__patch_200_response"
}
}
},
"description" : "OK"
}
},
"security" : [ {
"BearerAuth" : [ ]
} ],
"summary" : "Confirm experience",
"tags" : [ "space" ],
"x-code-samples" : [ {
"label" : "Python",
"lang" : "python",
"source" : "from acontext import AcontextClient\n\nclient = AcontextClient(api_key='sk_project_token')\n\n# Confirm experience and save data\nconfirmation = client.spaces.confirm_experience(\n space_id='space-uuid',\n experience_id='experience-uuid',\n save=True\n)\nprint(f\"Saved confirmation: {confirmation.experience_data}\")\n\n# Confirm experience without saving (just delete)\nclient.spaces.confirm_experience(\n space_id='space-uuid',\n experience_id='experience-uuid',\n save=False\n)\n"
}, {
"label" : "JavaScript",
"lang" : "javascript",
"source" : "import { AcontextClient } from '@acontext/acontext';\n\nconst client = new AcontextClient({ apiKey: 'sk_project_token' });\n\n// Confirm experience and save data\nconst confirmation = await client.spaces.confirmExperience('space-uuid', 'experience-uuid', {\n save: true\n});\nconsole.log(`Saved confirmation: ${JSON.stringify(confirmation.experience_data)}`);\n\n// Confirm experience without saving (just delete)\nawait client.spaces.confirmExperience('space-uuid', 'experience-uuid', {\n save: false\n});\n"
} ],
"x-codegen-request-body-name" : "request"
}
},
"/space/{space_id}/experience_search" : {
"get" : {
"description" : "Retrieve the experience search results for a given query within a space by its ID",
Expand Down Expand Up @@ -1922,6 +2046,15 @@
},
"type" : "object"
},
"handler.ConfirmExperienceReq" : {
"properties" : {
"save" : {
"type" : "boolean"
}
},
"required" : [ "save" ],
"type" : "object"
},
"handler.ConnectToSpaceReq" : {
"properties" : {
"space_id" : {
Expand Down Expand Up @@ -2280,6 +2413,30 @@
},
"type" : "object"
},
"model.ExperienceConfirmation" : {
"properties" : {
"created_at" : {
"type" : "string"
},
"experience_data" : {
"properties" : { },
"type" : "object"
},
"id" : {
"type" : "string"
},
"space_id" : {
"type" : "string"
},
"task_id" : {
"type" : "string"
},
"updated_at" : {
"type" : "string"
}
},
"type" : "object"
},
"model.Message" : {
"properties" : {
"created_at" : {
Expand Down Expand Up @@ -2473,6 +2630,23 @@
},
"type" : "object"
},
"service.ListExperienceConfirmationsOutput" : {
"properties" : {
"has_more" : {
"type" : "boolean"
},
"items" : {
"items" : {
"$ref" : "#/components/schemas/model.ExperienceConfirmation"
},
"type" : "array"
},
"next_cursor" : {
"type" : "string"
}
},
"type" : "object"
},
"service.ListSessionsOutput" : {
"properties" : {
"has_more" : {
Expand Down Expand Up @@ -2782,6 +2956,30 @@
"type" : "object"
} ]
},
"_space__space_id__experience_confirmations_get_200_response" : {
"allOf" : [ {
"$ref" : "#/components/schemas/serializer.Response"
}, {
"properties" : {
"data" : {
"$ref" : "#/components/schemas/service.ListExperienceConfirmationsOutput"
}
},
"type" : "object"
} ]
},
"_space__space_id__experience_confirmations__experience_id__patch_200_response" : {
"allOf" : [ {
"$ref" : "#/components/schemas/serializer.Response"
}, {
"properties" : {
"data" : {
"$ref" : "#/components/schemas/model.ExperienceConfirmation"
}
},
"type" : "object"
} ]
},
"_space__space_id__experience_search_get_200_response" : {
"allOf" : [ {
"$ref" : "#/components/schemas/serializer.Response"
Expand Down
1 change: 1 addition & 0 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
{
"group": "Advance",
"pages": [
"learn/advance/wait-user",
"learn/advance/design-complex",
"learn/advance/experience-agent"
]
Expand Down
77 changes: 77 additions & 0 deletions docs/learn/advance/wait-user.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
title: "Wait for User Confirmation"
description: "Acontext can wait for user confirmation before actually leanring skills"
---

By default, Acontext will automatically learn skills from completed tasks.
But this might not be what the user wants, some agent apps, like Manus, provide a way to let users decide whether to learn the skills or not.

Acontext also supports this.


## Enable User Confirmation
You can enable user confirmation by setting the `project_enable_user_confirmation_on_new_experiences` to `true` in the project settings.

```yaml config.yaml
project_enable_user_confirmation_on_new_experiences: true
```

## Obtain the Unconfirmed Experiences

Once you enable it, for every worth-learning experience, Acontext will wait for user confirmation before actually learning skills.
You can obtain the unconfirmed experiences by calling the `get_unconfirmed_experiences` method.

<CodeGroup>
```python Python
experiences = client.spaces.get_unconfirmed_experiences(space_id=space.id)

for e in experiences.items:
print(f"{e.id}: {e.experience_data}")
```

```typescript TypeScript
const experiences = await client.spaces.getUnconfirmedExperiences(spaceId);

for (const e of experiences.items) {
console.log(`${e.id}: ${JSON.stringify(e.experience_data)}`);
}
```
</CodeGroup>

You can render those experiences in UI and let users decide whether to learn the skills or not.

Experience data consists of the following fields:
```json experience_data
{
"type": "sop",
"data": {
"use_when": "Implement google authentication",
"preferences": "Use NextAuth;",
"tool_sops": [
{
"tool_name": "ls",
"action": "find the middleware folder",
},
...
]
}
```

## Confirm the Experience
Once user decided, you can confirm the experience by calling the `confirm_experience` method.

<CodeGroup>
```python Python
# Use this Experience
client.spaces.confirm_experience(space_id=space.id, experience_id=experience.id, save=True)
# Reject this Experience
client.spaces.confirm_experience(space_id=space.id, experience_id=experience.id, save=False)
```

```typescript TypeScript
// Use this Experience
await client.spaces.confirmExperience(spaceId, experienceId, { save: true });
// Reject this Experience
await client.spaces.confirmExperience(spaceId, experienceId, { save: false });
```
</CodeGroup>
59 changes: 59 additions & 0 deletions src/client/acontext-py/src/acontext/resources/async_spaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from .._utils import build_params
from ..client_types import AsyncRequesterProtocol
from ..types.space import (
ExperienceConfirmation,
ListExperienceConfirmationsOutput,
ListSpacesOutput,
SearchResultBlockItem,
Space,
Expand Down Expand Up @@ -186,3 +188,60 @@ async def semantic_grep(
"GET", f"/space/{space_id}/semantic_grep", params=params or None
)
return [SearchResultBlockItem.model_validate(item) for item in data]

async def get_unconfirmed_experiences(
self,
space_id: str,
*,
limit: int | None = None,
cursor: str | None = None,
time_desc: bool | None = None,
) -> ListExperienceConfirmationsOutput:
"""Get all unconfirmed experiences in a space with cursor-based pagination.

Args:
space_id: The UUID of the space.
limit: Maximum number of confirmations to return (1-200, default 20).
cursor: Cursor for pagination. Use the cursor from the previous response to get the next page.
time_desc: Order by created_at descending if True, ascending if False (default False).

Returns:
ListExperienceConfirmationsOutput containing the list of experience confirmations and pagination information.
"""
params = build_params(limit=limit, cursor=cursor, time_desc=time_desc)
data = await self._requester.request(
"GET",
f"/space/{space_id}/experience_confirmations",
params=params or None,
)
return ListExperienceConfirmationsOutput.model_validate(data)

async def confirm_experience(
self,
space_id: str,
experience_id: str,
*,
save: bool,
) -> ExperienceConfirmation | None:
"""Confirm an experience confirmation.

If save is False, delete the row. If save is True, get the data first,
then delete the row.

Args:
space_id: The UUID of the space.
experience_id: The UUID of the experience confirmation.
save: If True, get data before deleting. If False, just delete.

Returns:
ExperienceConfirmation object if save is True, None otherwise.
"""
payload = {"save": save}
data = await self._requester.request(
"PATCH",
f"/space/{space_id}/experience_confirmations/{experience_id}",
json_data=payload,
)
if data is None:
return None
return ExperienceConfirmation.model_validate(data)
Loading
Loading