Skip to content

feat: add Context schemas for agent/skill/file hub repos#2745

Merged
Jacob Lee (jacoblee93) merged 12 commits intomainfrom
vishnu/sdk-context-schemas
Apr 22, 2026
Merged

feat: add Context schemas for agent/skill/file hub repos#2745
Jacob Lee (jacoblee93) merged 12 commits intomainfrom
vishnu/sdk-context-schemas

Conversation

@vishnu-ssuresh
Copy link
Copy Markdown
Contributor

@vishnu-ssuresh Vishnu Suresh (vishnu-ssuresh) commented Apr 20, 2026

Summary

Adds the new types for the Context hub surface (agents, skills) in both the Python and JS/TS SDKs. Types-only, no behavior change.

Python (python/langsmith/schemas.py): MAX_CONTEXT_ENTRIES, FileEntry, AgentEntry, SkillEntry, Entry (discriminated union), AgentContext, SkillContext, DirectoryCommitInfo, DirectoryCommitResponse.

JS/TS (js/src/schemas.ts): MAX_CONTEXT_ENTRIES, FileEntry, AgentEntry, SkillEntry, Entry, AgentContext, SkillContext, DirectoryCommitResponse.

Stack

Part 1 of 4. Follow-ups:

  1. This PR — Context schemas (py + js)
  2. feat(python): add Context and AsyncContext classes with unit tests
  3. feat(js): add agent/skill hub methods on Client with unit tests
  4. test: integration tests for Context (python + js)

Release Note

none

Test plan

  • No runtime changes — type definitions only
  • Follow-up PRs add the implementation and tests that exercise these types

Adds the new types that both the Python and JS/TS SDKs need for
the Context hub surface (agents, skills, files):

Python (schemas.py): FileEntry, AgentEntry, SkillEntry, Entry
(discriminated union), AgentContext, SkillContext, FileContext,
ListContextResponse.

JS/TS (schemas.ts): FileEntry, AgentEntry, SkillEntry, Entry,
AgentContext, SkillContext, DirectoryCommitResponse.

No behavior change — types only. SDK implementations and tests
land in follow-up PRs.
Python already exports schemas.MAX_CONTEXT_ENTRIES = 500. Mirror it
on the JS side so the commit-size limit has a single named source on
both SDKs instead of a hard-coded literal.
…e DirectoryCommitResponse structure

Added commit_id to AgentContext and SkillContext interfaces for better tracking of commits. Updated DirectoryCommitResponse to include a structured commit object with detailed fields, enhancing clarity and usability of the response data.
The backend rejects file-type repos at /directories/commits, so
removing pull_file/push_file/delete_file/list_files from the Python
SDK for parity with JS. FileContext becomes unused when those methods
go away.
Vishnu Suresh (vishnu-ssuresh) added a commit that referenced this pull request Apr 20, 2026
## Summary

Adds live-backend round-trip integration tests for the Context hub
surface, landing the test coverage that was held out of the impl PRs.

## Coverage

Each file runs 8 tests covering every public method — `push`, `pull`,
`delete`, `list` — plus null-entry deletion and second-commit update.
Agent and skill variants are tested symmetrically.

- **Python sync** (`python/tests/integration_tests/test_context.py`) — 8
tests against `Client.context`
- **Python async**
(`python/tests/integration_tests/test_context_async.py`) — 8 tests
against `AsyncClient.context`
- **JS** (`js/src/tests/context.int.test.ts`) — 8 tests against `Client`

## Stack

Top of the stack. Depends on:

1. #2745 — Context schemas (py + js)
2. #2746 — Python impl
3. #2747 — JS impl
4. **#2748 (this PR)** — integration tests

Upstream PRs must land before this is reviewable on its own.

## Release Note

none

## Test plan

- [x] Python tests collect cleanly via `uv run pytest --collect-only`
- [x] JS tests compile via `tsc --noEmit`
- [ ] Live backend run: Python sync 8/8 + async 8/8 pass against
`beta.api.smith.langchain.com`
- [ ] Live backend run: JS 8/8 pass

---------

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Comment thread js/src/schemas.ts Outdated
@jacoblee93 Jacob Lee (jacoblee93) merged commit 473e195 into main Apr 22, 2026
67 of 72 checks passed
@jacoblee93 Jacob Lee (jacoblee93) deleted the vishnu/sdk-context-schemas branch April 22, 2026 22:43
Vishnu Suresh (vishnu-ssuresh) added a commit that referenced this pull request Apr 23, 2026
…2746)

## Summary

Adds Hub agent/skill operations to the Python SDK, exposed directly on
`Client` and `AsyncClient` as flat methods. Mirrors the existing prompt
surface (`pull_prompt` / `push_prompt` / `list_prompts`) rather than
nesting under a namespace. Prompt methods are untouched.

### Example

```python
from langsmith import Client
c = Client()

url = c.push_agent(
    "-/my-agent",
    files={
        "AGENTS.md": {"type": "file", "content": "# My Agent\n"},
        "skills/review": {"type": "skill", "repo_handle": "code-reviewer"},  # link
        "legacy.md": None,  # delete
    },
    description="demo agent",
)

agent = c.pull_agent("-/my-agent")  # linked skills expanded up to 3 levels
```

## URL layout

| Operation | Path | Served by |
|---|---|---|
| Create / get / update / list / delete repo | `/repos/...` |
smith-backend |
| Pull / commit / delete directory |
`/v1/platform/hub/repos/{owner}/{repo}/directories[/commits]` | smith-go
|

## Design choices

- **Flat on `Client` / `AsyncClient`.** Matches existing `pull_prompt` /
`push_prompt` / `list_prompts`, and matches the JS SDK (#2747) + Java's
planned hub surface. No public namespace accessor.
- **Internal `Context` / `AsyncContext` classes.** Method bodies live
there; flat methods on `Client` / `AsyncClient` are thin delegating
wrappers (lazy-imported). Keeps Python's `Client` class definition
readable without committing callers to a namespaced API.
- **Sync + async parity.** Each flat method has an `async` equivalent on
`AsyncClient`.
- **`_create_repo` swallows 409.** Prevents races between exists-check
and create, matching smith-go's backfill.

## Public surface

Added on both `Client` (sync) and `AsyncClient` (async):

- `pull_agent` / `push_agent` / `delete_agent` / `agent_exists` /
`list_agents`
- `pull_skill` / `push_skill` / `delete_skill` / `skill_exists` /
`list_skills`

## Stack

1. #2745 — Context schemas (py + js) — **base**
2. **#2746 (this PR)** — Python impl + unit tests + Python integration
tests
3. #2747 — JS impl + unit tests + JS integration tests

## Release Note

Adds `Client.pull_agent` / `push_agent` / `delete_agent` /
`agent_exists` / `list_agents` (plus skill equivalents) and their async
counterparts on `AsyncClient` for managing non-prompt Hub repos.

## Test plan

- [x] Unit tests in `tests/unit_tests/test_context.py` (27 tests)
- [x] `uv run pytest tests/unit_tests/test_context.py` — pass
- [x] Python integration round-trips in
`tests/integration_tests/test_context.py` and
`tests/integration_tests/test_context_async.py` (8 sync + 8 async)
- [x] `uv run ruff check langsmith/client.py langsmith/async_client.py`
— pass
Vishnu Suresh (vishnu-ssuresh) added a commit that referenced this pull request Apr 23, 2026
## Summary

Ports the hub (agent/skill) surface to the JS/TS SDK. Methods sit
directly on `Client` — matches how `pullPrompt` / `pushPrompt` /
`listPrompts` are already exposed, and matches the flat surface chosen
on the Python side (#2746). Prompt methods are untouched.

### Example

```ts
import { Client } from "langsmith";
const c = new Client();

const url = await c.pushAgent("-/my-agent", {
  files: {
    "AGENTS.md": { type: "file", content: "# My Agent\n" },
    "skills/review": { type: "skill", repo_handle: "code-reviewer" },  // link
    "legacy.md": null,  // delete
  },
  description: "demo agent",
});

const agent = await c.pullAgent("-/my-agent");  // linked skills expanded up to 3 levels
```

## Public surface (added on `Client`)

- `pullAgent` / `pushAgent` / `deleteAgent` / `agentExists` /
`listAgents`
- `pullSkill` / `pushSkill` / `deleteSkill` / `skillExists` /
`listSkills`

## URL layout

| Operation | Path | Served by |
|---|---|---|
| Create / get / update / list / delete repo | `/repos/...` |
smith-backend |
| Pull / commit / delete directory |
`/v1/platform/hub/repos/{owner}/{repo}/directories[/commits]` | smith-go
|

## Design choices

- **Methods directly on `Client`.** Matches `pullPrompt` / `pushPrompt`
/ `listPrompts` and the Python SDK's flat surface (#2746). No wrapper
class.
- **`HubRepoType = "agent" | "skill"` type alias** in schemas.ts, used
at every call site instead of inline `"agent" | "skill"` unions.
- **`parseHubIdentifier`** wrapper in `utils/prompts.ts` used across all
5 hub call sites (`agentExists`, `skillExists`, `_pullDirectory`,
`_pushDirectory`, `_deleteDirectory`) so hub-specific identifier-parsing
changes land in one place.
- **`_pullDirectory` sends `repo_type` as a query param.** Server
currently ignores it; becomes load-bearing when server-side type
validation lands. Mirrors the same change on Python.
- **`AgentContext` / `SkillContext` carry only `commit_id` /
`commit_hash` / `files`.** No `owner` / `repo` fields — those aren't in
the server response, and callers already parse them from the identifier
they pass in. Matches Python schema.
- **Sync-only surface.** JS has a single `Client`; no sync/async split.
- **`_createRepo` swallows 409.** Prevents races between exists-check
and create, matching Python.
- **`listAgents` / `listSkills` as async iterators.** Mirror
`listPrompts`, auto-paginating `/repos` with the `repo_type` filter.

## Stack

1. #2745 — Context schemas (py + js) — **base**
2. #2746 — Python impl + unit tests + Python integration tests
3. **#2747 (this PR)** — JS impl + unit tests + JS integration tests

## Release Note

Adds `pullAgent` / `pushAgent` / `pullSkill` / `pushSkill` /
`deleteAgent` / `deleteSkill` / `listAgents` / `listSkills` /
`agentExists` / `skillExists` on `Client` for managing non-prompt Hub
repos.

## Test plan

- [x] Unit tests in `src/tests/context.test.ts` (25 tests)
- [x] `pnpm test src/tests/context.test.ts` — pass
- [x] `pnpm run build` — TS clean
- [x] JS integration round-trips in `src/tests/context.int.test.ts` (8
tests)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants