tavus-cli 0.7.0__tar.gz → 0.8.0__tar.gz

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.
Files changed (113) hide show
  1. tavus_cli-0.8.0/.release-please-manifest.json +3 -0
  2. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/CHANGELOG.md +18 -0
  3. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/PKG-INFO +27 -6
  4. tavus_cli-0.8.0/PROMPT.md +65 -0
  5. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/README.md +26 -5
  6. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/docs/gemini-enterprise/test-queries.md +1 -1
  7. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/packages/tavus/pyproject.toml +2 -2
  8. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/packages/tavus-mcp/pyproject.toml +2 -2
  9. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/pyproject.toml +1 -1
  10. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/skills/tavus-agentic-pals/SKILL.md +12 -4
  11. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/__init__.py +1 -1
  12. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/cli/main.py +124 -8
  13. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/client/http.py +3 -7
  14. tavus_cli-0.8.0/src/tavus_mcp/sdk/recipes/deployments.py +216 -0
  15. tavus_cli-0.8.0/src/tavus_mcp/sdk/schemas/deployment.py +106 -0
  16. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/schemas/guardrail.py +4 -4
  17. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/schemas/pal.py +0 -1
  18. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/server.py +122 -5
  19. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/integration/test_cli.py +12 -0
  20. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/integration/test_mcp_server.py +125 -0
  21. tavus_cli-0.8.0/tests/unit/test_deployments.py +189 -0
  22. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/uv.lock +1 -1
  23. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/package-lock.json +2 -2
  24. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/package.json +1 -1
  25. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/src/oauth.ts +44 -29
  26. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/src/tavus.ts +365 -2
  27. tavus_cli-0.8.0/workers/tavus-mcp/src/version.ts +1 -0
  28. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/test/oauth-session.test.ts +6 -2
  29. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/test/tavus.test.ts +229 -0
  30. tavus_cli-0.7.0/.release-please-manifest.json +0 -3
  31. tavus_cli-0.7.0/workers/tavus-mcp/src/version.ts +0 -1
  32. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/.agents/plugins/marketplace.json +0 -0
  33. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/.env.example +0 -0
  34. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/.github/workflows/ci.yml +0 -0
  35. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/.github/workflows/deploy-cloudflare-worker.yml +0 -0
  36. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/.github/workflows/pr-reviews.yml +0 -0
  37. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/.github/workflows/pypi-cli.yml +0 -0
  38. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/.github/workflows/tail-cloudflare-worker.yml +0 -0
  39. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/.github/workflows/validate-staging-deployment.yml +0 -0
  40. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/.gitignore +0 -0
  41. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/AGENTS.md +0 -0
  42. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/docs/chatgpt-plugin.md +0 -0
  43. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/docs/gemini-enterprise/README.md +0 -0
  44. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/docs/gemini-enterprise/listing.md +0 -0
  45. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/docs/usage-observability.md +0 -0
  46. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/packages/tavus/README.md +0 -0
  47. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/packages/tavus-mcp/README.md +0 -0
  48. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/plugins/tavus-pal/assets/icon-dark.svg +0 -0
  49. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/plugins/tavus-pal/assets/icon.svg +0 -0
  50. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/plugins/tavus-pal/mcp.json +0 -0
  51. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/plugins/tavus-pal/plugin.json +0 -0
  52. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/release-please-config.json +0 -0
  53. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/scripts/__init__.py +0 -0
  54. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/scripts/build_chatgpt_plugin.py +0 -0
  55. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/scripts/check_release_versions.py +0 -0
  56. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/skills/tavus-agentic-pals/agents/openai.yaml +0 -0
  57. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/skills/tavus-agentic-pals/references/build-and-verify.md +0 -0
  58. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/skills/tavus-agentic-pals/references/builder-workflow.md +0 -0
  59. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/skills/tavus-agentic-pals/references/chat-mode.md +0 -0
  60. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/skills/tavus-agentic-pals/references/examples.md +0 -0
  61. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/cli/__init__.py +0 -0
  62. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/__init__.py +0 -0
  63. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/auth/__init__.py +0 -0
  64. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/auth/keyring_store.py +0 -0
  65. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/auth/oauth.py +0 -0
  66. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/auth/session.py +0 -0
  67. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/client/__init__.py +0 -0
  68. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/daily_transport.py +0 -0
  69. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/env.py +0 -0
  70. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/errors.py +0 -0
  71. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/pal_urls.py +0 -0
  72. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/patch.py +0 -0
  73. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/recipes/__init__.py +0 -0
  74. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/recipes/build_and_verify.py +0 -0
  75. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/recipes/capabilities.py +0 -0
  76. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/recipes/carrier_builder.py +0 -0
  77. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/recipes/knowledge.py +0 -0
  78. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/recipes/options.py +0 -0
  79. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/recipes/quickstart.py +0 -0
  80. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/recipes/scaffold_embed.py +0 -0
  81. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/recipes/templates.py +0 -0
  82. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/recipes/tool_reuse.py +0 -0
  83. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/schemas/__init__.py +0 -0
  84. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/schemas/file_manifest.py +0 -0
  85. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/schemas/objective.py +0 -0
  86. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/schemas/pronunciation.py +0 -0
  87. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/src/tavus_mcp/sdk/schemas/tool.py +0 -0
  88. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/conftest.py +0 -0
  89. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/integration/test_client.py +0 -0
  90. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/integration/test_oauth.py +0 -0
  91. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_auth.py +0 -0
  92. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_build_and_verify.py +0 -0
  93. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_builder.py +0 -0
  94. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_capabilities.py +0 -0
  95. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_daily_transport.py +0 -0
  96. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_env.py +0 -0
  97. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_guardrail_schema.py +0 -0
  98. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_objective_schema.py +0 -0
  99. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_pal_schema.py +0 -0
  100. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_patch.py +0 -0
  101. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_pronunciation_schema.py +0 -0
  102. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_release_versions.py +0 -0
  103. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_scaffold_embed.py +0 -0
  104. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_tool_reuse.py +0 -0
  105. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/tests/unit/test_tool_schema.py +0 -0
  106. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/.dev.vars.example +0 -0
  107. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/src/index.ts +0 -0
  108. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/src/oauth-grant.ts +0 -0
  109. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/src/oauth-session.ts +0 -0
  110. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/test/parity.test.ts +0 -0
  111. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/test/worker-runtime.ts +0 -0
  112. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/tsconfig.json +0 -0
  113. {tavus_cli-0.7.0 → tavus_cli-0.8.0}/workers/tavus-mcp/wrangler.jsonc +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.8.0"
3
+ }
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.0](https://github.com/Tavus-Engineering/tavus-mcp/compare/v0.7.0...v0.8.0) (2026-10-08)
4
+
5
+
6
+ ### Features
7
+
8
+ * create deployments from MCP so agents can put a PAL on a site ([#59](https://github.com/Tavus-Engineering/tavus-mcp/issues/59)) ([15079b3](https://github.com/Tavus-Engineering/tavus-mcp/commit/15079b3ce3dc941a6c59ad5278241923a93e715d))
9
+ * **worker:** accept sign-in from VS Code, v0, Lovable and Replit ([#61](https://github.com/Tavus-Engineering/tavus-mcp/issues/61)) ([c220a74](https://github.com/Tavus-Engineering/tavus-mcp/commit/c220a74cb8835767583adf242586c4b2484dea4d))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * **guardrails:** let the hosted server patch guardrail_ids and drop guardrails_id ([#12](https://github.com/Tavus-Engineering/tavus-mcp/issues/12)) ([ae389a5](https://github.com/Tavus-Engineering/tavus-mcp/commit/ae389a5399eae609f416b59a59b4e77dd3001a37))
15
+
16
+
17
+ ### Documentation
18
+
19
+ * add a coding-agent prompt for the MCP server ([#58](https://github.com/Tavus-Engineering/tavus-mcp/issues/58)) ([293f2eb](https://github.com/Tavus-Engineering/tavus-mcp/commit/293f2eb6d8804f85cc444382cbf9cd84ee2598e4))
20
+
3
21
  ## [0.7.0](https://github.com/Tavus-Engineering/tavus-mcp/compare/v0.6.0...v0.7.0) (2026-10-07)
4
22
 
5
23
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: tavus-cli
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: Tavus CLI and MCP server for agentic PAL creation and editing.
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: fastmcp>=2.0.0
@@ -29,8 +29,9 @@ MCP-aware client) drive the same platform through the API:
29
29
  - **MCP server.** The full PAL surface as MCP tools: the guided build
30
30
  (`tavus_pal_build_and_verify`), chat-mode text testing, and CRUD for PALs,
31
31
  tools, knowledge, guardrails, objectives, pronunciation dictionaries,
32
- capabilities, faces, and voices. Run it locally over stdio, or connect to
33
- the hosted server at `https://mcp.tavus.io/mcp`.
32
+ capabilities, faces, and voices, plus deployments that put a PAL on a
33
+ landing page, an embed or a widget. Run it locally over stdio, or connect
34
+ to the hosted server at `https://mcp.tavus.io/mcp`.
34
35
  - **`tavus` CLI.** The same surface as shell commands, published to PyPI as
35
36
  [`tavus-cli`](https://pypi.org/project/tavus-cli/). Scripted PAL authoring
36
37
  and publishing, JSON round-tripping, browser login with OS-keychain storage.
@@ -56,9 +57,28 @@ OAuth metadata and dynamic client registration, so the client sends you
56
57
  through Tavus browser sign-in. The developer portal mints a per-user API key;
57
58
  the Worker keeps it encrypted server-side and issues expiring OAuth tokens.
58
59
  The API key never appears in client configuration or browser callback URLs.
59
- Claude and ChatGPT callback
60
- URLs are accepted automatically; other hosted clients must be registered
61
- through `MCP_OAUTH_CLIENTS`.
60
+
61
+ Dynamic client registration accepts loopback callbacks from any local client
62
+ (Claude Code, Codex, Gemini CLI) and the hosted callbacks of Claude, ChatGPT,
63
+ Cursor, VS Code, v0, Lovable and Replit. They are listed in `KNOWN_REMOTE_CLIENTS` in
64
+ `workers/tavus-mcp/src/oauth.ts`. To add a client, press Connect in it once,
65
+ read its callback from the Worker's `oauth_register_rejected` log line, and add
66
+ an entry with a test. Clients that don't use dynamic registration, such as
67
+ Gemini Enterprise, get a client ID and secret through the `MCP_OAUTH_CLIENTS`
68
+ secret, with their callback in `redirect_uris` (for Gemini Enterprise,
69
+ `https://vertexaisearch.cloud.google.com/oauth-redirect`).
70
+
71
+ `PROMPT.md` is the prompt for coding agents working with Tavus through this
72
+ server. Paste it into Claude Code, Codex or Cursor: it gets the client
73
+ connected, asks what the user wants to build, and states the contracts for
74
+ building, changing and testing a PAL and wiring its tools into the user's code.
75
+ Put a known PAL id or tool list above it and the agent will not ask for them.
76
+ When the user wants the PAL in front of people, the agent suggests a landing
77
+ page, embed or widget from the project, creates the deployment with
78
+ `tavus_deployment_create`, and either shares the landing page link or hands
79
+ off to the embed or widget prompt in tavus-examples
80
+ (`examples/embed-prompt.md`, `examples/widget-prompt.md`) with the
81
+ deployment id and the PAL's page tools already filled in.
62
82
 
63
83
  ### ChatGPT plugin
64
84
 
@@ -148,6 +168,7 @@ Command groups:
148
168
  | `tavus guardrail`, `tavus objective`, `tavus tool`, `tavus pronunciation-dictionary` | CRUD for each resource |
149
169
  | `tavus face`, `tavus resource`, `tavus skill` | account resource discovery |
150
170
  | `tavus conversation` | create or end CVI conversations |
171
+ | `tavus deployment` | `list`, `get`, `create` — put a PAL on a landing page, an embed or a widget |
151
172
  | `tavus auth`, `tavus doctor`, `tavus quickstart`, `tavus embed` | login, environment checks, one-call PAL + conversation, embed scaffolding |
152
173
 
153
174
  Examples:
@@ -0,0 +1,65 @@
1
+ You are working with Tavus from this coding session through the Tavus MCP server: building and changing PALs (Tavus's AI personas that hold real-time, face-to-face video conversations), giving them tools that act in my app, and testing them. The server is hosted at `https://mcp.tavus.io/mcp` and exposes `tavus_*` tools that read and write my Tavus account. The tools return data and file manifests; they never write files. You write any code into my repo yourself.
2
+
3
+ Before anything else, check that the `tavus_*` tools are available to you. If they are not, give me the one setup step for my client and stop until I have done it:
4
+
5
+ - Claude Code: `claude mcp add -s user --transport http tavus https://mcp.tavus.io/mcp`
6
+ - Codex: `codex mcp add tavus --url https://mcp.tavus.io/mcp`, then `codex mcp login tavus`
7
+ - Cursor and other MCP clients: add `https://mcp.tavus.io/mcp` as a remote (HTTP) MCP server named `tavus`
8
+ - Claude.ai and ChatGPT: add a custom connector with the same URL
9
+
10
+ Sign-in happens in the browser on first use, with my Tavus account. Some clients need a restart before new tools show up. Once the tools are there, call `tavus_mcp_health_check` and continue only when it passes.
11
+
12
+ Then read the reference pages below (the `.md` URLs return plain markdown) and ask me these things:
13
+
14
+ 1. What we are doing. One of these, a mix, or something else entirely:
15
+ (a) build a new PAL from my description,
16
+ (b) change a PAL I already have (its prompt, greeting, objectives, guardrails, knowledge, capabilities, face or voice),
17
+ (c) give a PAL tools that act in my app or call my backend, and write the code in this repo that handles them,
18
+ (d) test a PAL by text against specific questions,
19
+ (e) put a PAL in front of people: inside this app, on my website, or as a link I can share,
20
+ (f) your own idea, described in your words.
21
+ If I am not sure what to build, look at this repo, then suggest what fits and say why.
22
+ 2. Which PAL, for anything other than a new one, unless its id is already given above this prompt or came from a build earlier in this session; then use it and do not ask. If I do not know the id, list my PALs with `tavus_pal_list` and `sort: "desc"` (newest first) and let me pick. Do not invent an id.
23
+ 3. For tools, unless they are already listed above this prompt: what each one should do, and whether it runs on the page (in the browser, next to the conversation) or on my backend (a URL Tavus calls). Look at this repo before asking, since the answer is often in the code.
24
+
25
+ How the server works
26
+
27
+ - One account, production. The hosted server acts on the Tavus account I signed in with, against the production API. There is no environment switch and no API key in the client config.
28
+ - Everything on a PAL is a resource with an id: faces, voices, guardrails, objectives, Knowledge documents, tools. Get ids from the matching list call (`tavus_face_list`, `tavus_voice_list`, `tavus_guardrail_list`, `tavus_objective_list`, `tavus_document_list`, `tavus_tool_list`) or from `tavus_describe_pal_options`, which returns one PAL with everything attachable to it.
29
+ - Tools are first-class records. A tool is created once with `tavus_tool_create` and attached with `tavus_pal_tools_attach`. Writing tools inline under `layers.llm.tools` is rejected.
30
+ - The five PAL Maker capabilities (Magic Canvas, Slide Presenter, Web Search, Perception, Memory) go through `tavus_pal_capability_attach`, `tavus_pal_capability_patch` and `tavus_pal_capability_detach`, not raw patches.
31
+ - Every conversation is billed like any other, including the build's own test turns, chat-mode tests and previews.
32
+
33
+ How to do the common things properly
34
+
35
+ These are the contracts the server keeps. Exact parameters and response shapes are in the reference below; the order of operations is here, because that is what tends to get invented.
36
+
37
+ - Building a new PAL. Use `tavus_pal_build_and_verify`; it is the standard path. You run the interview first: ask me plain questions, up to 12, about who the PAL talks to, what a good conversation achieves, the tone, what it must never say or do, what it should know (links to documents), and what it should do in my app. Ask only what my description leaves open. Pass my description as `prompt`, the questions and my answers as `interview`, and your summary of each part as `briefs`. The call takes one to three minutes. It drafts the personality, objectives, guardrails and greeting, picks a face unless I asked for one (`face_id`), publishes the PAL, runs test conversations and judges them. Read `verdict.overall` (`pass`, `partial` or `fail`), then the summary and any failing evidence, before you tell me it works. Tools can only be attached once the PAL exists, so the build's test turns run without them and tool checks in the verdict fail; attach the tools, then rerun those turns with chat mode before you tell me the tools work. Give me the `pal_url` it returns; that opens the PAL in the PAL Maker. Use `tavus_pal_create` or `tavus_quickstart` only when I hand you a finished system prompt and ask you to skip the build.
38
+ - Changing an existing PAL. Call `tavus_pal_get` and `tavus_describe_pal_options` first, and take ids and patch paths from what they return. Make the smallest change with `tavus_patch_pal` (JSON Patch operations such as `replace` on `/greeting`), or use the dedicated tools for capabilities, Knowledge and tools. A change applies to every conversation the PAL starts from then on, including on my live site, so tell me what will change and get a yes before patching a PAL that is already in use.
39
+ - Giving the PAL a tool. Check `tavus_tool_list` first and attach an existing tool when its name, parameters and delivery fit. When you create a new one that overlaps an existing tool, tell me which tool you saw and why it does not fit. The tool's `description` is what tells the PAL when to call it, so write it as an instruction. `delivery` decides where the call goes: `{ "app_message": true }` (the default) sends it to the page running the conversation, and `delivery.api` makes Tavus call a backend URL. Then write the handler in this repo with the exact tool name and parameter schema, so the two halves match. On a page that uses `<tavus-embed>` or `<tavus-widget>`, the call arrives as `tavus:tool-call` `{ name, arguments, tool_call_id }` with `arguments` as a JSON string, and the page replies with `sendMessage({ event_type: "conversation.tool_result", properties: { tool_call_id, output, status: "success" } })`; the host communication page below has the full contract. A tool that is not attached to the PAL never fires, however the code is wired.
40
+ - Giving the PAL knowledge. Create a Knowledge document from a URL anyone can reach with `tavus_document_create`, then attach it with `tavus_pal_knowledge_add`. The hosted server cannot read files on my machine; for a local file, ask me to upload it in the PAL Maker's Knowledge section or to host it at a URL. Before you tell me what a document says, read what Tavus indexed with `tavus_document_chunks`.
41
+ - Testing by text. `tavus_chat_start` starts a text-only conversation with the PAL, `tavus_chat_turn` sends one message and waits for the reply, and `tavus_chat_end` ends it. Always end the conversations you start. The first turn is slower while the conversation starts up. Replies are not deterministic, so judge behaviour (did it ask for the order number, did it refuse the pricing promise) rather than exact wording.
42
+ - Seeing it on video. `tavus_pal_preview` starts a full video conversation and returns its URL for me to open. Do it after the text tests pass, and only when I want to see or hear the PAL.
43
+ - Putting the PAL in front of people. A deployment is what makes a PAL reachable, and there are three kinds. A landing page is a page Tavus hosts, with its own link, for when there is no site in this repo or I want something to send around. Embed puts the conversation inside a page of my app: a section, a card, a step in a flow. Widget is a floating launcher on every page of my site. Pick one from what this repo is, propose it with a reason, and let me decide. If I want the PAL to act on the page (open a product, fill a form), create and attach those tools before deploying, so the handoff below includes them.
44
+ - Creating the deployment. Call `tavus_deployment_list` with the PAL id first and offer to reuse a deployment that already fits. Otherwise ask me what `tavus_deployment_create` needs: whether each visitor gets their own memory of past calls; for embed or widget, where the site is hosted, as origins such as `https://www.example.com`, plus `http://localhost:<port>` from this repo's dev server if I want to try it locally (an empty list lets any site load it); for a landing page, a headline and one sentence you draft from what the PAL does; and how much use to allow, since every call is billed and a deployment has no limits unless I set them: calls per day across all visitors, calls per day per visitor, calls at the same moment, and the longest a call may last. Suggest numbers that fit what I am building, and let me say no limit. A deployment is live and public as soon as it is created, so show me these values and get a yes first.
45
+ - Handing off. `tavus_deployment_create` returns an `integration` block. For a landing page, give me `landing_page_url`. For embed or widget, read `prompt_url` and follow that prompt with `prompt_header` placed above it, so it does not ask for the deployment id or the page tools again; write a handler for every entry in `page_tools`, reusing any handler you already wrote in this session. When the PAL's tools change later, `tavus_deployment_get` returns the current list. Changing a deployment's settings or taking it down happens in the [Tavus PAL Maker](https://maker.tavus.io). Do not use `tavus_scaffold_embed` for a site: it wraps the URL of a single conversation, which stops working when that conversation ends.
46
+
47
+ Not possible, not needed, or not yours to do
48
+
49
+ - Do not ask me for an API key, and do not put one in the MCP config, an env file or the chat. Sign-in is the browser flow above.
50
+ - Changing or taking down a deployment, billing, team members and account settings are not available through the MCP server. Send me to the PAL Maker or the developer portal for those.
51
+ - Do not invent ids for PALs, faces, voices, guardrails, objectives, documents or tools. Every id comes from a list or get call.
52
+ - Do not delete PALs, tools, guardrails, objectives, documents or pronunciation dictionaries, and do not end conversations you did not start, unless I ask for that exact action.
53
+ - Do not retry a failed write in a loop. Read the error; if it looks like sign-in or connectivity, call `tavus_mcp_health_check` and tell me what it says.
54
+ - Tool names and parameters are exactly what the server lists. If a tool is not in your tool list, it does not exist.
55
+
56
+ Reference, current and authoritative; this prompt is not a substitute for it:
57
+
58
+ - Connecting a client, tool delivery to the page or a backend: https://docs.tavus.io/sections/agent-tools/mcp-server.md
59
+ - Every MCP tool and its parameters: https://docs.tavus.io/sections/agent-tools/mcp-tools-reference.md
60
+ - The guided build and how to read its verdict: https://docs.tavus.io/sections/agent-tools/pal-build-and-verify.md
61
+ - Handling tool calls on a page with `<tavus-embed>` or `<tavus-widget>`: https://docs.tavus.io/sections/deployments/host-communication.md
62
+ - Coding-agent prompt for `<tavus-embed>`: https://raw.githubusercontent.com/Tavus-Engineering/tavus-examples/main/examples/embed-prompt.md
63
+ - Coding-agent prompt for `<tavus-widget>`: https://raw.githubusercontent.com/Tavus-Engineering/tavus-examples/main/examples/widget-prompt.md
64
+ - Deployments: https://docs.tavus.io/sections/deployments/landing-page.md, https://docs.tavus.io/sections/deployments/embed.md and https://docs.tavus.io/sections/deployments/widget.md
65
+ - Full documentation index: https://docs.tavus.io/llms.txt
@@ -7,8 +7,9 @@ MCP-aware client) drive the same platform through the API:
7
7
  - **MCP server.** The full PAL surface as MCP tools: the guided build
8
8
  (`tavus_pal_build_and_verify`), chat-mode text testing, and CRUD for PALs,
9
9
  tools, knowledge, guardrails, objectives, pronunciation dictionaries,
10
- capabilities, faces, and voices. Run it locally over stdio, or connect to
11
- the hosted server at `https://mcp.tavus.io/mcp`.
10
+ capabilities, faces, and voices, plus deployments that put a PAL on a
11
+ landing page, an embed or a widget. Run it locally over stdio, or connect
12
+ to the hosted server at `https://mcp.tavus.io/mcp`.
12
13
  - **`tavus` CLI.** The same surface as shell commands, published to PyPI as
13
14
  [`tavus-cli`](https://pypi.org/project/tavus-cli/). Scripted PAL authoring
14
15
  and publishing, JSON round-tripping, browser login with OS-keychain storage.
@@ -34,9 +35,28 @@ OAuth metadata and dynamic client registration, so the client sends you
34
35
  through Tavus browser sign-in. The developer portal mints a per-user API key;
35
36
  the Worker keeps it encrypted server-side and issues expiring OAuth tokens.
36
37
  The API key never appears in client configuration or browser callback URLs.
37
- Claude and ChatGPT callback
38
- URLs are accepted automatically; other hosted clients must be registered
39
- through `MCP_OAUTH_CLIENTS`.
38
+
39
+ Dynamic client registration accepts loopback callbacks from any local client
40
+ (Claude Code, Codex, Gemini CLI) and the hosted callbacks of Claude, ChatGPT,
41
+ Cursor, VS Code, v0, Lovable and Replit. They are listed in `KNOWN_REMOTE_CLIENTS` in
42
+ `workers/tavus-mcp/src/oauth.ts`. To add a client, press Connect in it once,
43
+ read its callback from the Worker's `oauth_register_rejected` log line, and add
44
+ an entry with a test. Clients that don't use dynamic registration, such as
45
+ Gemini Enterprise, get a client ID and secret through the `MCP_OAUTH_CLIENTS`
46
+ secret, with their callback in `redirect_uris` (for Gemini Enterprise,
47
+ `https://vertexaisearch.cloud.google.com/oauth-redirect`).
48
+
49
+ `PROMPT.md` is the prompt for coding agents working with Tavus through this
50
+ server. Paste it into Claude Code, Codex or Cursor: it gets the client
51
+ connected, asks what the user wants to build, and states the contracts for
52
+ building, changing and testing a PAL and wiring its tools into the user's code.
53
+ Put a known PAL id or tool list above it and the agent will not ask for them.
54
+ When the user wants the PAL in front of people, the agent suggests a landing
55
+ page, embed or widget from the project, creates the deployment with
56
+ `tavus_deployment_create`, and either shares the landing page link or hands
57
+ off to the embed or widget prompt in tavus-examples
58
+ (`examples/embed-prompt.md`, `examples/widget-prompt.md`) with the
59
+ deployment id and the PAL's page tools already filled in.
40
60
 
41
61
  ### ChatGPT plugin
42
62
 
@@ -126,6 +146,7 @@ Command groups:
126
146
  | `tavus guardrail`, `tavus objective`, `tavus tool`, `tavus pronunciation-dictionary` | CRUD for each resource |
127
147
  | `tavus face`, `tavus resource`, `tavus skill` | account resource discovery |
128
148
  | `tavus conversation` | create or end CVI conversations |
149
+ | `tavus deployment` | `list`, `get`, `create` — put a PAL on a landing page, an embed or a widget |
129
150
  | `tavus auth`, `tavus doctor`, `tavus quickstart`, `tavus embed` | login, environment checks, one-call PAL + conversation, embed scaffolding |
130
151
 
131
152
  Examples:
@@ -10,7 +10,7 @@ Each test-env Tavus account is pre-seeded with at least:
10
10
  - 3 pals (`customer-support-demo`, `interviewer-demo`, `tutor-demo`)
11
11
  - 5 system faces
12
12
  - 2 documents
13
- - 1 guardrail set
13
+ - 1 guardrail
14
14
  - 1 objective tree
15
15
 
16
16
  Credentials and exact pal/face IDs are delivered out-of-band per
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "tavus"
3
- version = "0.7.0" # x-release-please-version
3
+ version = "0.8.0" # x-release-please-version
4
4
  description = "Official alias for tavus-cli, the Tavus CLI and MCP server."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
7
7
  dependencies = [
8
- "tavus-cli==0.7.0", # x-release-please-version
8
+ "tavus-cli==0.8.0", # x-release-please-version
9
9
  ]
10
10
 
11
11
  [project.urls]
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "tavus-mcp"
3
- version = "0.7.0" # x-release-please-version
3
+ version = "0.8.0" # x-release-please-version
4
4
  description = "Official alias for tavus-cli, which provides the tavus-mcp MCP server."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
7
7
  dependencies = [
8
- "tavus-cli==0.7.0", # x-release-please-version
8
+ "tavus-cli==0.8.0", # x-release-please-version
9
9
  ]
10
10
 
11
11
  [project.urls]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tavus-cli"
3
- version = "0.7.0"
3
+ version = "0.8.0"
4
4
  description = "Tavus CLI and MCP server for agentic PAL creation and editing."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: tavus-agentic-pals
3
- description: Use when Codex needs to create, inspect, edit, test, or embed Tavus pals with the tavus CLI or tavus-mcp MCP server. Covers the guided PAL Maker build (tavus_pal_build_and_verify / tavus pal build), chat-mode text testing, local TEST/STG/PROD environment selection, dev-portal login, API-key storage, safe pal patching, account resource discovery, conversation creation, embed scaffolding, and CLI/MCP examples.
3
+ description: Use when Codex needs to create, inspect, edit, test, or embed Tavus pals with the tavus CLI or tavus-mcp MCP server. Covers the guided PAL Maker build (tavus_pal_build_and_verify / tavus pal build), chat-mode text testing, local TEST/STG/PROD environment selection, dev-portal login, API-key storage, safe pal patching, account resource discovery, conversation creation, deployments to a landing page, embed or widget, embed scaffolding, and CLI/MCP examples.
4
4
  ---
5
5
 
6
6
  # Tavus Agentic PALs
@@ -142,7 +142,15 @@ Conversation and resource tools:
142
142
  - `tavus_resource_list(resource, limit)` for `guardrails`, `objectives`, `documents`, `voices`, `skills`, or `tools`
143
143
  - `tavus_scaffold_embed(conversation_url, target, component_name)`
144
144
 
145
- `tavus_scaffold_embed` returns a file manifest. The MCP host agent writes files if the user wants files created.
145
+ `tavus_scaffold_embed` returns a file manifest. The MCP host agent writes files if the user wants files created. It wraps one conversation URL; use a deployment to put a PAL on a site.
146
+
147
+ Deployment tools (a PAL on a landing page, an embed or a widget):
148
+
149
+ - `tavus_deployment_list(pal_id?, channel?, status?, limit?, page?)` — newest first; check it before creating so an existing deployment gets reused
150
+ - `tavus_deployment_get(deployment_id)` — the deployment plus its `integration` block, with the PAL's current page tools
151
+ - `tavus_deployment_create(pal_id, channel, unique_memory_per_visitor, allowed_origins?, page_title?, page_description?, page_cta?, page_logo?, name?, context?, daily_call_limit?, daily_call_limit_per_user?, concurrent_call_limit?, max_call_duration?)` — creates an active deployment. `channel` is `landing-page`, `embed` or `widget`. Ask the user about memory per visitor and the limits (no limit unless set; `max_call_duration` is in seconds); embed and widget need `allowed_origins` (where the site is hosted, `[]` for any site); a landing page needs `page_title` and `page_description`. It is public at once, so confirm the values first.
152
+
153
+ The `integration` block holds `landing_page_url` for a landing page. For an embed or widget it holds the snippet, `prompt_url` (the tavus-examples coding-agent prompt), `prompt_header` (the deployment id and page-tool lines that go above that prompt) and `page_tools` (every attached tool with `delivery.app_message`). Changing or taking down a deployment happens in the PAL Maker.
146
154
 
147
155
  Guardrail resources (attach via `/guardrail_ids` or `/guardrail_tags`):
148
156
 
@@ -248,11 +256,11 @@ Prefer focused patches over full rebuilds:
248
256
  [
249
257
  {"op": "replace", "path": "/pal_name", "value": "Support Concierge v2"},
250
258
  {"op": "replace", "path": "/layers/conversational_flow/active_listening", "value": true},
251
- {"op": "replace", "path": "/guardrails_id", "value": "grd_123"}
259
+ {"op": "replace", "path": "/guardrail_ids", "value": ["grd_123", "grd_456"]}
252
260
  ]
253
261
  ```
254
262
 
255
- Common patch targets include `/system_prompt`, `/greeting`, `/context`, `/pal_name`, `/default_face_id`, `/objectives_id`, `/guardrails_id`, `/document_ids`, `/document_tags`, and nested layer paths under `/layers/llm`, `/layers/tts`, `/layers/stt`, `/layers/perception`, `/layers/conversational_flow`, `/layers/capabilities`, and `/layers/knowledge_base`.
263
+ Common patch targets include `/system_prompt`, `/greeting`, `/context`, `/pal_name`, `/default_face_id`, `/objectives_id`, `/guardrail_ids`, `/guardrail_tags`, `/document_ids`, `/document_tags`, and nested layer paths under `/layers/llm`, `/layers/tts`, `/layers/stt`, `/layers/perception`, `/layers/conversational_flow`, `/layers/capabilities`, and `/layers/knowledge_base`.
256
264
 
257
265
  ## Creation Patterns
258
266
 
@@ -1,4 +1,4 @@
1
1
  """Tavus CLI and MCP server package."""
2
2
 
3
3
  __all__ = ["__version__"]
4
- __version__ = "0.7.0" # x-release-please-version
4
+ __version__ = "0.8.0" # x-release-please-version
@@ -27,6 +27,11 @@ from tavus_mcp.sdk.recipes.capabilities import (
27
27
  list_pal_capabilities,
28
28
  patch_pal_capability,
29
29
  )
30
+ from tavus_mcp.sdk.recipes.deployments import (
31
+ compact_deployment_list,
32
+ create_deployment,
33
+ get_deployment,
34
+ )
30
35
  from tavus_mcp.sdk.recipes.knowledge import (
31
36
  add_pal_knowledge,
32
37
  list_pal_knowledge,
@@ -38,6 +43,7 @@ from tavus_mcp.sdk.recipes.knowledge import (
38
43
  from tavus_mcp.sdk.recipes.options import describe_pal_options
39
44
  from tavus_mcp.sdk.recipes.quickstart import quickstart as quickstart_recipe
40
45
  from tavus_mcp.sdk.recipes.scaffold_embed import scaffold_embed
46
+ from tavus_mcp.sdk.schemas.deployment import DEPLOYMENT_CREATE_ADAPTER
41
47
 
42
48
  HELP_CONTEXT = {"help_option_names": ["-h", "--help"]}
43
49
 
@@ -59,6 +65,7 @@ document_app = typer.Typer(no_args_is_help=True, context_settings=HELP_CONTEXT)
59
65
  skill_app = typer.Typer(no_args_is_help=True, context_settings=HELP_CONTEXT)
60
66
  builder_app = typer.Typer(no_args_is_help=True, context_settings=HELP_CONTEXT)
61
67
  chat_app = typer.Typer(no_args_is_help=True, context_settings=HELP_CONTEXT)
68
+ deployment_app = typer.Typer(no_args_is_help=True, context_settings=HELP_CONTEXT)
62
69
  app.add_typer(auth_app, name="auth")
63
70
  app.add_typer(pal_app, name="pal")
64
71
  pal_app.add_typer(pal_tools_app, name="tools")
@@ -76,6 +83,7 @@ app.add_typer(skill_app, name="skill")
76
83
  app.add_typer(pronunciation_app, name="pronunciation-dictionary")
77
84
  app.add_typer(builder_app, name="builder")
78
85
  app.add_typer(chat_app, name="chat")
86
+ app.add_typer(deployment_app, name="deployment")
79
87
  console = Console()
80
88
 
81
89
 
@@ -274,14 +282,11 @@ def pal_create(
274
282
  None, "--memory", help="Initial seed memory. Repeat for multiple."
275
283
  ),
276
284
  objectives_id: str | None = typer.Option(None, "--objectives-id"),
277
- guardrails_id: str | None = typer.Option(
278
- None, "--guardrails-id", help="Legacy guardrail-set id."
279
- ),
280
285
  guardrail_ids: list[str] | None = typer.Option(
281
- None, "--guardrail-id", help="Repeat for multiple. New flat shape."
286
+ None, "--guardrail-id", help="Attach a flat guardrail by id. Repeat for multiple."
282
287
  ),
283
288
  guardrail_tags: list[str] | None = typer.Option(
284
- None, "--guardrail-tag", help="Repeat for multiple. New flat shape."
289
+ None, "--guardrail-tag", help="Attach flat guardrails by tag. Repeat for multiple."
285
290
  ),
286
291
  document_ids: list[str] | None = typer.Option(
287
292
  None, "--document-id", help="Repeat for multiple."
@@ -320,8 +325,6 @@ def pal_create(
320
325
  body["memories"] = list(memories)
321
326
  if objectives_id:
322
327
  body["objectives_id"] = objectives_id
323
- if guardrails_id:
324
- body["guardrails_id"] = guardrails_id
325
328
  if guardrail_ids:
326
329
  body["guardrail_ids"] = list(guardrail_ids)
327
330
  if guardrail_tags:
@@ -1187,7 +1190,11 @@ def guardrail_list(
1187
1190
  type: str = typer.Option("user", help="user | system | all"),
1188
1191
  name_or_uuid: str | None = typer.Option(None),
1189
1192
  tags: str | None = typer.Option(None, help="Comma-separated tag filter."),
1190
- legacy: bool = typer.Option(False, help="Return the legacy set-shape list."),
1193
+ legacy: bool = typer.Option(
1194
+ False,
1195
+ help="Read-only: surface older grouped-shape rows. Off by default; "
1196
+ "this SDK works with flat, per-rule guardrails.",
1197
+ ),
1191
1198
  verbose: bool = typer.Option(False, help="Include persona_refs + guardrail_type."),
1192
1199
  json_output: bool = typer.Option(False, "--json"),
1193
1200
  ) -> None:
@@ -2031,6 +2038,115 @@ def _resource(client: TavusClient, resource: str) -> Any:
2031
2038
  return getattr(client, attr)
2032
2039
 
2033
2040
 
2041
+ @deployment_app.command("list")
2042
+ def deployment_list(
2043
+ pal_id: str | None = typer.Option(None, "--pal-id"),
2044
+ channel: str | None = typer.Option(None, help="landing-page | embed | widget"),
2045
+ status: str | None = typer.Option(None, help="draft | active | inactive"),
2046
+ limit: int = typer.Option(25),
2047
+ page: int = typer.Option(0),
2048
+ json_output: bool = typer.Option(False, "--json"),
2049
+ ) -> None:
2050
+ """List deployments, newest first."""
2051
+
2052
+ async def run() -> Any:
2053
+ async with TavusClient.from_env(surface="cli") as client:
2054
+ return await client.deployments.list(
2055
+ pal_id=pal_id,
2056
+ channel=channel,
2057
+ status=status,
2058
+ limit=limit,
2059
+ page=page,
2060
+ include_thumbnails="false",
2061
+ )
2062
+
2063
+ data = compact_deployment_list(_run(run()))
2064
+ if json_output:
2065
+ _json(data)
2066
+ return
2067
+ _print_rows(data, ["deployment_id", "name", "channel", "status", "pal_id", "updated_at"])
2068
+
2069
+
2070
+ @deployment_app.command("get")
2071
+ def deployment_get(deployment_id: str) -> None:
2072
+ """Show a deployment with its landing page link, or its snippet and page tools."""
2073
+
2074
+ async def run() -> Any:
2075
+ async with TavusClient.from_env(surface="cli") as client:
2076
+ return await get_deployment(client, deployment_id)
2077
+
2078
+ _json(_run(run()))
2079
+
2080
+
2081
+ @deployment_app.command("create")
2082
+ def deployment_create(
2083
+ pal_id: str = typer.Option(..., "--pal-id"),
2084
+ channel: str = typer.Option(..., help="landing-page | embed | widget"),
2085
+ unique_memory_per_visitor: bool = typer.Option(
2086
+ ...,
2087
+ "--memory-per-visitor/--shared-memory",
2088
+ help="Give each visitor their own memory of past calls, or share one across visitors.",
2089
+ ),
2090
+ allowed_origins: list[str] | None = typer.Option(
2091
+ None,
2092
+ "--allowed-origin",
2093
+ help="Site allowed to load an embed or widget, such as https://www.example.com. "
2094
+ "Repeat for more. Required for embed and widget; pass --any-origin to allow any site.",
2095
+ ),
2096
+ any_origin: bool = typer.Option(False, "--any-origin", help="Let any site load it."),
2097
+ page_title: str | None = typer.Option(
2098
+ None, help="Landing page headline. Required for a landing page."
2099
+ ),
2100
+ page_description: str | None = typer.Option(
2101
+ None, help="Sentence under the headline. Required for a landing page."
2102
+ ),
2103
+ page_logo: str | None = typer.Option(None, help="Landing page logo image URL."),
2104
+ name: str | None = typer.Option(
2105
+ None, help='Defaults to "<PAL name> Link", "Embed" or "Widget".'
2106
+ ),
2107
+ context: str | None = typer.Option(
2108
+ None, help="What every call from this deployment should know."
2109
+ ),
2110
+ daily_call_limit: int | None = typer.Option(None, help="Calls per day across all visitors."),
2111
+ daily_call_limit_per_user: int | None = typer.Option(None, help="Calls per day per visitor."),
2112
+ concurrent_call_limit: int | None = typer.Option(None, help="Calls at the same moment."),
2113
+ max_call_duration: int | None = typer.Option(None, help="Length of one call, in seconds."),
2114
+ ) -> None:
2115
+ """Create a live deployment. It is public as soon as it exists. Calls are
2116
+ unlimited unless you set the limit options."""
2117
+
2118
+ async def run() -> Any:
2119
+ fields: dict[str, Any] = {
2120
+ "pal_id": pal_id,
2121
+ "channel": channel,
2122
+ "unique_memory_per_visitor": unique_memory_per_visitor,
2123
+ "allowed_origins": [] if any_origin else allowed_origins,
2124
+ "page_title": page_title,
2125
+ "page_description": page_description,
2126
+ "page_logo": page_logo,
2127
+ "name": name,
2128
+ "context": context,
2129
+ "limits": {
2130
+ key: value
2131
+ for key, value in {
2132
+ "daily_call_limit": daily_call_limit,
2133
+ "daily_call_limit_per_user": daily_call_limit_per_user,
2134
+ "concurrent_call_limit": concurrent_call_limit,
2135
+ "max_call_duration": max_call_duration,
2136
+ }.items()
2137
+ if value is not None
2138
+ }
2139
+ or None,
2140
+ }
2141
+ request = DEPLOYMENT_CREATE_ADAPTER.validate_python(
2142
+ {key: value for key, value in fields.items() if value is not None}
2143
+ )
2144
+ async with TavusClient.from_env(surface="cli") as client:
2145
+ return await create_deployment(client, request)
2146
+
2147
+ _json(_run(run()))
2148
+
2149
+
2034
2150
  def _print_rows(data: Any, columns: list[str]) -> None:
2035
2151
  rows = data.get("data", data) if isinstance(data, dict) else data
2036
2152
  if not isinstance(rows, list):
@@ -140,6 +140,7 @@ class TavusClient:
140
140
  self.tools = ToolResource(self)
141
141
  self.pronunciation_dictionaries = PronunciationDictionaryResource(self)
142
142
  self.builders = BuilderResource(self)
143
+ self.deployments = Resource(self, "deployments")
143
144
 
144
145
  @classmethod
145
146
  def from_env(
@@ -477,8 +478,8 @@ class PalResource(Resource):
477
478
 
478
479
 
479
480
  class GuardrailResource(Resource):
480
- """Flat-list guardrails (no more sets). Adds `validate` and `tags` to the
481
- base CRUD surface."""
481
+ """Flat-list guardrails (no more sets). Adds `tags` to the base CRUD
482
+ surface."""
482
483
 
483
484
  def __init__(self, client: TavusClient) -> None:
484
485
  super().__init__(client, "guardrails")
@@ -491,11 +492,6 @@ class GuardrailResource(Resource):
491
492
  validated = GuardrailUpdate.model_validate(payload).model_dump(exclude_none=True)
492
493
  return await self.client.request("PATCH", f"/guardrails/{resource_id}", json=validated)
493
494
 
494
- async def validate(self, payload: dict[str, Any]) -> Any:
495
- """`POST /v2/guardrails/validate` — checks a legacy set-shape payload
496
- without persisting. Useful before bulk-importing."""
497
- return await self.client.request("POST", "/guardrails/validate", json=payload)
498
-
499
495
  async def tags(self, **params: Any) -> Any:
500
496
  """`GET /v2/guardrails/tags` — KB-shaped `{tags, total_count}`."""
501
497
  return await self.client.request("GET", "/guardrails/tags", params=_clean(params))